﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область ПрограммныйИнтерфейс

// Инициализирует общие параметры формы выполнения задачи.
//
// Параметры:
//  ФормаЗадачи            - ФормаКлиентскогоПриложения - форма выполнения задачи.
//  ЗадачаОбъект           - ЗадачаОбъект     - объект задачи.
//  ЭлементГруппаСостояние - ГруппаФормы      - группа с информации о состоянии задачи.
//  ЭлементДатаИсполнения  - ПолеФормы        - поле с датой исполнения задачи.
//
Процедура ФормаЗадачиПриСозданииНаСервере(ФормаЗадачи, ЗадачаОбъект, 
	ЭлементГруппаСостояние, ЭлементДатаИсполнения) Экспорт
	
	ФормаЗадачи.ТолькоПросмотр = ЗадачаОбъект.Выполнена;

	Если ЗадачаОбъект.Выполнена Тогда
		Если ЭлементГруппаСостояние <> Неопределено Тогда
			ЭлементГруппаСостояние.Видимость = Истина;
		КонецЕсли;
		Родитель = ?(ЭлементГруппаСостояние <> Неопределено, ЭлементГруппаСостояние, ФормаЗадачи);
		Элемент = ФормаЗадачи.Элементы.Найти("__СостояниеЗадачиКартинка");
		Если Элемент = Неопределено Тогда
			Элемент = ФормаЗадачи.Элементы.Добавить("__СостояниеЗадачиКартинка", Тип("ДекорацияФормы"), Родитель);
			Элемент.Вид = ВидДекорацииФормы.Картинка;
			Элемент.Картинка = БиблиотекаКартинок.Информация;
		КонецЕсли;
		
		Элемент = ФормаЗадачи.Элементы.Найти("__СостояниеЗадачи");
		Если Элемент = Неопределено Тогда
			Элемент = ФормаЗадачи.Элементы.Добавить("__СостояниеЗадачи", Тип("ДекорацияФормы"), Родитель);
			Элемент.Вид = ВидДекорацииФормы.Надпись;
			Элемент.Высота = 0; // автовысота
			Элемент.АвтоМаксимальнаяШирина = Ложь;
		КонецЕсли;
		ИспользоватьДатуИВремяВСрокахЗадач = ПолучитьФункциональнуюОпцию("ИспользоватьДатуИВремяВСрокахЗадач");
		ДатаИсполненияСтрокой = ?(ИспользоватьДатуИВремяВСрокахЗадач, 
			Формат(ЗадачаОбъект.ДатаИсполнения, "ДЛФ=DT"), Формат(ЗадачаОбъект.ДатаИсполнения, "ДЛФ=D"));
		Элемент.Заголовок = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Задача выполнена %1 пользователем %2.'"),
			ДатаИсполненияСтрокой, 
			ИсполнительСтрокой(ЗадачаОбъект.Исполнитель, ЗадачаОбъект.РольИсполнителя,
			ЗадачаОбъект.ОсновнойОбъектАдресации, ЗадачаОбъект.ДополнительныйОбъектАдресации));
	КонецЕсли;
	
	Если БизнесПроцессыИЗадачиВызовСервера.ЭтоВедущаяЗадача(ЗадачаОбъект.Ссылка) Тогда
		Если ЭлементГруппаСостояние <> Неопределено Тогда
			ЭлементГруппаСостояние.Видимость = Истина;
		КонецЕсли;
		Родитель = ?(ЭлементГруппаСостояние <> Неопределено, ЭлементГруппаСостояние, ФормаЗадачи);
		Элемент = ФормаЗадачи.Элементы.Найти("__ВедущаяЗадачаКартинка");
		Если Элемент = Неопределено Тогда
			Элемент = ФормаЗадачи.Элементы.Добавить("__ВедущаяЗадачаКартинка", Тип("ДекорацияФормы"), Родитель);
			Элемент.Вид = ВидДекорацииФормы.Картинка;
			Элемент.Картинка = БиблиотекаКартинок.Информация;
		КонецЕсли;
		
		Элемент = ФормаЗадачи.Элементы.Найти("__ВедущаяЗадача");
		Если Элемент = Неопределено Тогда
			Элемент = ФормаЗадачи.Элементы.Добавить("__ВедущаяЗадача", Тип("ДекорацияФормы"), Родитель);
			Элемент.Вид = ВидДекорацииФормы.Надпись;
			Элемент.Заголовок = НСтр("ru = 'Это ведущая задача для вложенных бизнес-процессов. Она будет выполнена автоматически при их завершении.'");
			Элемент.Высота = 0; // автовысота
			Элемент.АвтоМаксимальнаяШирина = Ложь;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

// Вызывается при создании формы списка задач на сервере.
//
// Параметры:
//  СписокЗадачИлиЕгоУсловноеОформление - ДинамическийСписок
//                                      - УсловноеОформлениеКомпоновкиДанных - условное оформление списка задач.
//
Процедура УстановитьОформлениеЗадач(Знач СписокЗадачИлиЕгоУсловноеОформление) Экспорт
	
	Если ТипЗнч(СписокЗадачИлиЕгоУсловноеОформление) = Тип("ДинамическийСписок") Тогда
		УсловноеОформлениеСпискаЗадач = СписокЗадачИлиЕгоУсловноеОформление.КомпоновщикНастроек.Настройки.УсловноеОформление;
		УсловноеОформлениеСпискаЗадач.ИдентификаторПользовательскойНастройки = "ОсновноеОформление";
	Иначе
		УсловноеОформлениеСпискаЗадач = СписокЗадачИлиЕгоУсловноеОформление;
	КонецЕсли;
	
	// Удаление предустановленных элементов оформления.
	Предустановленные = Новый Массив;
	Элементы = УсловноеОформлениеСпискаЗадач.Элементы;
	Для каждого ЭлементУсловногоОформления Из Элементы Цикл
		Если ЭлементУсловногоОформления.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный Тогда
			Предустановленные.Добавить(ЭлементУсловногоОформления);
		КонецЕсли;
	КонецЦикла;
	Для каждого ЭлементУсловногоОформления Из Предустановленные Цикл
		Элементы.Удалить(ЭлементУсловногоОформления);
	КонецЦикла;
		
	// Установка оформления для просроченных задач.
	ЭлементУсловногоОформления = УсловноеОформлениеСпискаЗадач.Элементы.Добавить();
	ЭлементУсловногоОформления.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	
	ЭлементОтбораДанных = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбораДанных.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СрокИсполнения");
	ЭлементОтбораДанных.ВидСравнения = ВидСравненияКомпоновкиДанных.Заполнено;
	ЭлементОтбораДанных.Использование = Истина;
	
	ЭлементОтбораДанных = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбораДанных.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СрокИсполнения");
	ЭлементОтбораДанных.ВидСравнения = ВидСравненияКомпоновкиДанных.Меньше;
	ЭлементОтбораДанных.ПравоеЗначение = ТекущаяДатаСеанса();
	ЭлементОтбораДанных.Использование = Истина;
	
	ЭлементОтбораДанных = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбораДанных.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Выполнена");
	ЭлементОтбораДанных.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ЭлементОтбораДанных.ПравоеЗначение = Ложь;
	ЭлементОтбораДанных.Использование = Истина;
	
	ЭлементЦветаОформления = ЭлементУсловногоОформления.Оформление.Элементы.Найти("TextColor");
	ЭлементЦветаОформления.Значение =  Метаданные.ЭлементыСтиля.ПросроченныеДанныеЦвет.Значение;   
	ЭлементЦветаОформления.Использование = Истина;
	
	// Установка оформления для выполненных задач.
	ЭлементУсловногоОформления = УсловноеОформлениеСпискаЗадач.Элементы.Добавить();
	ЭлементУсловногоОформления.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	
	ЭлементОтбораДанных = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбораДанных.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Выполнена");
	ЭлементОтбораДанных.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ЭлементОтбораДанных.ПравоеЗначение = Истина;
	ЭлементОтбораДанных.Использование = Истина;
	
	ЭлементЦветаОформления = ЭлементУсловногоОформления.Оформление.Элементы.Найти("ЦветТекста");
	ЭлементЦветаОформления.Значение = Метаданные.ЭлементыСтиля.ВыполненнаяЗадача.Значение; 
	ЭлементЦветаОформления.Использование = Истина;
	
	// Установка оформления для задач, не принятых к исполнению.
	ЭлементУсловногоОформления = УсловноеОформлениеСпискаЗадач.Элементы.Добавить();
	ЭлементУсловногоОформления.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	
	ЭлементОтбораДанных = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбораДанных.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ПринятаКИсполнению");
	ЭлементОтбораДанных.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ЭлементОтбораДанных.ПравоеЗначение = Ложь;
	ЭлементОтбораДанных.Использование = Истина;
	
	ЭлементЦветаОформления = ЭлементУсловногоОформления.Оформление.Элементы.Найти("Шрифт");
	ЭлементЦветаОформления.Значение = Метаданные.ЭлементыСтиля.НеПринятыеКИсполнениюЗадачи.Значение; 
	ЭлементЦветаОформления.Использование = Истина;
	
	// Установка оформления для незаполненного поля "Срок".
	ЭлементУсловногоОформления = УсловноеОформлениеСпискаЗадач.Элементы.Добавить();
	ЭлементУсловногоОформления.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	
	ОформляемоеПоле = ЭлементУсловногоОформления.Поля.Элементы.Добавить();
	ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("СрокИсполнения");
	ОформляемоеПоле.Использование = Истина;
	
	ЭлементОтбораДанных = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбораДанных.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("СрокИсполнения");
	ЭлементОтбораДанных.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
	ЭлементОтбораДанных.ПравоеЗначение = Истина;
	ЭлементОтбораДанных.Использование = Истина;
	
	ЭлементЦветаОформления = ЭлементУсловногоОформления.Оформление.Элементы.Найти("ЦветТекста");
	ЭлементЦветаОформления.Значение = Метаданные.ЭлементыСтиля.ТекстЗапрещеннойЯчейкиЦвет.Значение;
	ЭлементЦветаОформления.Использование = Истина;
	
	ЭлементЦветаОформления = ЭлементУсловногоОформления.Оформление.Элементы.Найти("Текст");
	ЭлементЦветаОформления.Значение = НСтр("ru = 'Срок не указан'");
	ЭлементЦветаОформления.Использование = Истина;
	
	// Установка оформления для внешних пользователей, поле Автор пустое.
	Если Пользователи.ЭтоСеансВнешнегоПользователя() Тогда
			ЭлементУсловногоОформления = УсловноеОформлениеСпискаЗадач.Элементы.Добавить();
			ЭлементУсловногоОформления.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;

			ОформляемоеПоле = ЭлементУсловногоОформления.Поля.Элементы.Добавить();
			ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("Автор");
			ОформляемоеПоле.Использование = Истина;
			
			ЭлементОтбораДанных = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
			ЭлементОтбораДанных.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Автор");
			ЭлементОтбораДанных.ВидСравнения = ВидСравненияКомпоновкиДанных.НеРавно;
			ЭлементОтбораДанных.ПравоеЗначение = Пользователи.АвторизованныйПользователь();
			ЭлементОтбораДанных.Использование = Истина;

			ЭлементЦветаОформления = ЭлементУсловногоОформления.Оформление.Элементы.Найти("Текст");
			ЭлементЦветаОформления.Значение = НСтр("ru = 'Представитель организации'");
			ЭлементЦветаОформления.Использование = Истина;
	КонецЕсли;
	
КонецПроцедуры

// Вызывается при создании формы списка бизнес-процессов на сервере.
//
// Параметры:
//  УсловноеОформлениеБизнесПроцессов - УсловноеОформлениеКомпоновкиДанных - условное оформление списка бизнес-процессов.
//
Процедура УстановитьОформлениеБизнесПроцессов(Знач УсловноеОформлениеБизнесПроцессов) Экспорт
	
	// Наименование не задано
	ЭлементУсловногоОформления = УсловноеОформлениеБизнесПроцессов.Элементы.Добавить();
	ЭлементУсловногоОформления.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	
	ОформляемоеПоле = ЭлементУсловногоОформления.Поля.Элементы.Добавить();
	ОформляемоеПоле.Поле = Новый ПолеКомпоновкиДанных("Наименование");
	ОформляемоеПоле.Использование = Истина;
	
	ЭлементОтбораДанных = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбораДанных.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Наименование");
	ЭлементОтбораДанных.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
	
	ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("ЦветТекста", ЦветаСтиля.ТекстЗапрещеннойЯчейкиЦвет);
	ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("Текст", НСтр("ru = 'Без описания'"));
	
	// Завершенный бизнес-процесс
	ЭлементУсловногоОформления = УсловноеОформлениеБизнесПроцессов.Элементы.Добавить();
	ЭлементУсловногоОформления.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
	
	ЭлементОтбораДанных = ЭлементУсловногоОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбораДанных.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Завершен");
	ЭлементОтбораДанных.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ЭлементОтбораДанных.ПравоеЗначение = Истина;
	
	ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("ЦветТекста", ЦветаСтиля.ЗавершенныйБизнесПроцесс);
	
КонецПроцедуры

// Возвращает строковое представление исполнителя задачи Исполнитель, 
// либо указанного в параметрах РольИсполнителя, ОсновнойОбъектАдресации и ДополнительныйОбъектАдресации.
//
// Параметры:
//  Исполнитель                   - СправочникСсылка.Пользователи - исполнитель задачи.
//  РольИсполнителя               - СправочникСсылка.РолиИсполнителей - роль.
//  ОсновнойОбъектАдресации       - ЛюбаяСсылка - ссылка на основной объект адресации.
//  ДополнительныйОбъектАдресации - ЛюбаяСсылка - ссылка на дополнительный объект адресации.
//
// Возвращаемое значение:
//  Строка - строковое представление исполнителя задачи, например:
//           "Иванов Иван Иванович" - исполнитель, как указано в параметре Исполнитель;
//           "Главный бухгалтер" - роль исполнителя, указанная в параметре РольИсполнителя;
//           "Главный бухгалтер (ООО Солнышко)" - если роль указана вместе с основным объектом адресации;
//           "Главный бухгалтер (ОАО Солнышко, Филиал в г.Москва)" - если роль указана вместе с обоими объектами
//                                                                   адресации.
//
Функция ИсполнительСтрокой(Знач Исполнитель, Знач РольИсполнителя,
	Знач ОсновнойОбъектАдресации = Неопределено, Знач ДополнительныйОбъектАдресации = Неопределено) Экспорт
	
	Если ЗначениеЗаполнено(Исполнитель) Тогда
		Возврат Строка(Исполнитель)
	ИначеЕсли НЕ РольИсполнителя.Пустая() Тогда
		Возврат РольСтрокой(РольИсполнителя, ОсновнойОбъектАдресации, ДополнительныйОбъектАдресации);
	КонецЕсли;
	Возврат НСтр("ru = 'Не указан'");

КонецФункции

// Возвращает строковое представление роли РольИсполнителя и ее объектов адресации, если они заданы.
//
// Параметры:
//  РольИсполнителя               - СправочникСсылка.РолиИсполнителей - роль.
//  ОсновнойОбъектАдресации       - ЛюбаяСсылка - ссылка на основной объект адресации.
//  ДополнительныйОбъектАдресации - ЛюбаяСсылка - ссылка на дополнительный объект адресации.
// 
// Возвращаемое значение:
//  Строка - строковое представление роли, например:
//            "Главный бухгалтер" - роль исполнителя, указанная в параметре РольИсполнителя;
//            "Главный бухгалтер (ООО Солнышко)" - если роль указана вместе с основным объектом адресации;
//            "Главный бухгалтер (ОАО Солнышко, Филиал в г.Москва)" - если роль указана вместе с обоими объектами
//                                                                    адресации.
//
Функция РольСтрокой(Знач РольИсполнителя,
	Знач ОсновнойОбъектАдресации = Неопределено, Знач ДополнительныйОбъектАдресации = Неопределено) Экспорт
	
	Если НЕ РольИсполнителя.Пустая() Тогда
		Результат = Строка(РольИсполнителя);
		Если ОсновнойОбъектАдресации <> Неопределено Тогда
			Результат = Результат + " (" + Строка(ОсновнойОбъектАдресации);
			Если ДополнительныйОбъектАдресации <> Неопределено Тогда
				Результат = Результат + " ," + Строка(ДополнительныйОбъектАдресации);
			КонецЕсли;
			Результат = Результат + ")";
		КонецЕсли;
		Возврат Результат;
	КонецЕсли;
	Возврат "";

КонецФункции

// Помечает на удаление все задачи указанного бизнес-процесса (или снимает отметку).
//
// Параметры:
//  БизнесПроцессСсылка - ОпределяемыйТип.БизнесПроцесс - бизнес-процесс, задачи которого нужно пометить на удаление.
//  ПометкаУдаления     - Булево - значение свойства ПометкаУдаления для задач.
//
Процедура УстановитьПометкуУдаленияЗадач(БизнесПроцессСсылка, ПометкаУдаления) Экспорт
	
	ПредставлениеСсылки = Строка(БизнесПроцессСсылка);
	
	НачатьТранзакцию();
	Попытка
		Блокировка = Новый БлокировкаДанных;
		ЭлементБлокировки = Блокировка.Добавить("Задача.ЗадачаИсполнителя");
		ЭлементБлокировки.УстановитьЗначение("БизнесПроцесс", БизнесПроцессСсылка);
		Блокировка.Заблокировать();
		
		Запрос = Новый Запрос("ВЫБРАТЬ
			|	Задачи.Ссылка КАК Ссылка 
			|ИЗ
			|	Задача.ЗадачаИсполнителя КАК Задачи
			|ГДЕ
			|	Задачи.БизнесПроцесс = &БизнесПроцесс");
		Запрос.УстановитьПараметр("БизнесПроцесс", БизнесПроцессСсылка);
		Выборка = Запрос.Выполнить().Выбрать();
		
		Пока Выборка.Следующий() Цикл
			ЗадачаОбъект = Выборка.Ссылка.ПолучитьОбъект();
			ЗадачаОбъект.УстановитьПометкуУдаления(ПометкаУдаления);
		КонецЦикла;
		
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрации(), УровеньЖурналаРегистрации.Ошибка, 
			БизнесПроцессСсылка.Метаданные(), ПредставлениеСсылки, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры	

// Установить формат отображения и редактирования поля формы типа Дата
// в зависимости от настроек подсистемы.
//
// Параметры:
//  ПолеДаты - ПолеФормы - элемент управления формы, поле со значением типа Дата.
//
Процедура УстановитьФорматДаты(ПолеДаты) Экспорт
	
	ИспользоватьДатуИВремяВСрокахЗадач = ПолучитьФункциональнуюОпцию("ИспользоватьДатуИВремяВСрокахЗадач");
	СтрокаФормата = ?(ИспользоватьДатуИВремяВСрокахЗадач, "ДЛФ=DT", "ДЛФ=D");
	Если ПолеДаты.Вид = ВидПоляФормы.ПолеВвода Тогда
		ПолеДаты.ФорматРедактирования = СтрокаФормата;
	Иначе	
		ПолеДаты.Формат               = СтрокаФормата;
	КонецЕсли;
	ПолеДаты.Ширина                   = ?(ИспользоватьДатуИВремяВСрокахЗадач, 0, 9);
	
КонецПроцедуры

// Получить бизнес-процессы ведущей задачи ЗадачаСсылка.
//
// Параметры:
//   ЗадачаСсылка - ЗадачаСсылка.ЗадачаИсполнителя - ведущая задача.
//   ДляИзменения - Булево - если Истина, то следует установить исключительную управляемую блокировку 
//                           на все бизнес-процессы указанной ведущей задачи. По умолчанию, Ложь.
// Возвращаемое значение:
//    Массив из ОпределяемыйТип.БизнесПроцесс
// 
Функция БизнесПроцессыВедущейЗадачи(ЗадачаСсылка, ДляИзменения = Ложь) Экспорт
	
	Результат = ВыбратьБизнесПроцессыВедущейЗадачи(ЗадачаСсылка, ДляИзменения);
	Возврат Результат.Выгрузить().ВыгрузитьКолонку("Ссылка");
		
КонецФункции

// Возвращает дату завершения указанного бизнес-процесса,
// полученную как максимальная дата исполнения задач бизнес-процесса.
//
// Параметры:
//  БизнесПроцессСсылка - ОпределяемыйТип.БизнесПроцесс
// 
// Возвращаемое значение:
//  Дата
//
Функция ДатаЗавершенияБизнесПроцесса(БизнесПроцессСсылка) Экспорт
	
	ВыполнитьПроверкуПравДоступа("Чтение", БизнесПроцессСсылка.Метаданные());
	УстановитьПривилегированныйРежим(Истина);
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	МАКСИМУМ(ЗадачаИсполнителя.ДатаИсполнения) КАК МаксДатаИсполнения
		|ИЗ
		|	Задача.ЗадачаИсполнителя КАК ЗадачаИсполнителя
		|ГДЕ
		|	ЗадачаИсполнителя.БизнесПроцесс = &БизнесПроцесс
		|	И ЗадачаИсполнителя.Выполнена = ИСТИНА";
	Запрос.УстановитьПараметр("БизнесПроцесс", БизнесПроцессСсылка);
	
	Результат = Запрос.Выполнить();
	Если Результат.Пустой() Тогда 
		Возврат ТекущаяДатаСеанса();
	КонецЕсли;	
	
	Выборка = Результат.Выбрать();
	Выборка.Следующий();
	Возврат Выборка.МаксДатаИсполнения;
	
КонецФункции	

// Возвращает бизнес-процессы, подчиненные указанной задаче.
//
// Параметры:
//  ЗадачаСсылка  - ЗадачаСсылка.ЗадачаИсполнителя
//  ДляИзменения  - Булево - если Истина, то следует установить исключительную управляемую блокировку 
//                           на все бизнес-процессы, подчиненные указанной задаче. По умолчанию, Ложь.
//
// Возвращаемое значение:
//   Массив из ОпределяемыйТип.БизнесПроцесс
//
Функция БизнесПроцессыГлавнойЗадачи(ЗадачаСсылка, ДляИзменения = Ложь) Экспорт
	
	Результат = Новый Массив;
	Если ДляИзменения Тогда
		
		Блокировка = Новый БлокировкаДанных;
		
		Для Каждого ТипБизнесПроцесса Из Метаданные.ОпределяемыеТипы.БизнесПроцесс.Тип.Типы() Цикл
			
			МетаданныеБизнесПроцесса = Метаданные.НайтиПоТипу(ТипБизнесПроцесса);
			
			// У бизнес-процесса может и не быть главной задачи.
			РеквизитГлавнаяЗадача = МетаданныеБизнесПроцесса.Реквизиты.Найти("ГлавнаяЗадача");
			Если РеквизитГлавнаяЗадача = Неопределено Тогда
				Продолжить;
			КонецЕсли;
				
			ЭлементБлокировки = Блокировка.Добавить(МетаданныеБизнесПроцесса.ПолноеИмя());
			ЭлементБлокировки.УстановитьЗначение("ГлавнаяЗадача", ЗадачаСсылка);
			
		КонецЦикла;
		Блокировка.Заблокировать();
	КонецЕсли;
	
	ШаблонЗапроса = "ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	Таблица.Ссылка КАК Ссылка
		|ИЗ
		|	#Таблица КАК Таблица
		|ГДЕ
		|	Таблица.ГлавнаяЗадача = &ГлавнаяЗадача";
			
	ТекстыЗапросов = Новый Массив;
	Для Каждого ТипБизнесПроцесса Из Метаданные.ОпределяемыеТипы.БизнесПроцесс.Тип.Типы() Цикл
		
		МетаданныеБизнесПроцесса = Метаданные.НайтиПоТипу(ТипБизнесПроцесса);
		
		// У бизнес-процесса может не быть главной задачи.
		РеквизитГлавнаяЗадача = МетаданныеБизнесПроцесса.Реквизиты.Найти("ГлавнаяЗадача");
		Если РеквизитГлавнаяЗадача = Неопределено Тогда
			Продолжить;
		КонецЕсли;
			
		ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "#Таблица", МетаданныеБизнесПроцесса.ПолноеИмя());
		Если ТекстыЗапросов.Количество() > 0 Тогда
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ РАЗРЕШЕННЫЕ", "ВЫБРАТЬ"); // @query-part-1, @query-part-2
		КонецЕсли;
		ТекстыЗапросов.Добавить(ТекстЗапроса);
		
	КонецЦикла;
	
	Если ТекстыЗапросов.Количество() = 0 Тогда
		Возврат Результат;
	КонецЕсли;
	
	Запрос = Новый Запрос(СтрСоединить(ТекстыЗапросов, Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС));
	Запрос.УстановитьПараметр("ГлавнаяЗадача", ЗадачаСсылка);
	
	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Результат.Добавить(Выборка.Ссылка);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// Проверяет у текущего пользователя наличие прав на изменение состояния бизнес-процесса.
//
// Параметры:
//  БизнесПроцессОбъект - ОпределяемыйТип.БизнесПроцессОбъект
//
Процедура ПроверитьПраваНаИзменениеСостоянияБизнесПроцесса(БизнесПроцессОбъект) Экспорт
	
	Если Не ЗначениеЗаполнено(БизнесПроцессОбъект.Состояние) Тогда 
		БизнесПроцессОбъект.Состояние = Перечисления.СостоянияБизнесПроцессов.Активен;
	КонецЕсли;
	
	Если БизнесПроцессОбъект.ЭтоНовый() Тогда
		ПредыдущееСостояние = Перечисления.СостоянияБизнесПроцессов.Активен;
	Иначе
		ПредыдущееСостояние = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(БизнесПроцессОбъект.Ссылка, "Состояние");
	КонецЕсли;
	
	Если ПредыдущееСостояние <> БизнесПроцессОбъект.Состояние Тогда
		
		Если Не ЕстьПраваНаОстановкуБизнесПроцесса(БизнесПроцессОбъект) Тогда 
			ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Недостаточно прав для остановки бизнес-процесса ""%1"".'"),
				Строка(БизнесПроцессОбъект));
			ВызватьИсключение ТекстСообщения;
		КонецЕсли;
		
		Если ПредыдущееСостояние = Перечисления.СостоянияБизнесПроцессов.Активен Тогда
			
			Если БизнесПроцессОбъект.Завершен Тогда
				ВызватьИсключение НСтр("ru = 'Невозможно остановить завершенные бизнес-процессы.'");
			КонецЕсли;
				
			Если Не БизнесПроцессОбъект.Стартован Тогда
				ВызватьИсключение НСтр("ru = 'Невозможно остановить не стартовавшие бизнес-процессы.'");
			КонецЕсли;
			
		ИначеЕсли ПредыдущееСостояние = Перечисления.СостоянияБизнесПроцессов.Остановлен Тогда
			
			Если БизнесПроцессОбъект.Завершен Тогда
				ВызватьИсключение НСтр("ru = 'Невозможно сделать активными завершенные бизнес-процессы.'");
			КонецЕсли;
				
			Если Не БизнесПроцессОбъект.Стартован Тогда
				ВызватьИсключение НСтр("ru = 'Невозможно сделать активными не стартовавшие бизнес-процессы.'");
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

// Установить исключительную управляемую блокировку на указанные бизнес-процессы.
// Для вызова из обработчиков команд в динамических списках.
// Строки группировки динамического списка игнорируются.
//
// Параметры:
//   БизнесПроцессы - ОпределяемыйТип.БизнесПроцесс
//                  - Массив из ОпределяемыйТип.БизнесПроцесс
//
Процедура ЗаблокироватьБизнесПроцессы(БизнесПроцессы) Экспорт
	
	Блокировка = Новый БлокировкаДанных;
	Если ТипЗнч(БизнесПроцессы) = Тип("Массив") Тогда
		Для каждого БизнесПроцесс Из БизнесПроцессы Цикл
			
			Если ТипЗнч(БизнесПроцесс) = Тип("СтрокаГруппировкиДинамическогоСписка") Тогда
				Продолжить;
			КонецЕсли;	
			
			ЭлементБлокировки = Блокировка.Добавить(БизнесПроцесс.Метаданные().ПолноеИмя());
			ЭлементБлокировки.УстановитьЗначение("Ссылка", БизнесПроцесс);
		КонецЦикла;
	Иначе	
		Если ТипЗнч(БизнесПроцессы) = Тип("СтрокаГруппировкиДинамическогоСписка") Тогда
			Возврат;
		КонецЕсли;	
		ЭлементБлокировки = Блокировка.Добавить(БизнесПроцессы.Метаданные().ПолноеИмя());
		ЭлементБлокировки.УстановитьЗначение("Ссылка", БизнесПроцессы);
	КонецЕсли;
	Блокировка.Заблокировать();
	
КонецПроцедуры	

// Установить исключительную управляемую блокировку на указанные задачи.
// Для вызова из обработчиков команд в динамических списках.
// Строки группировки динамического списка игнорируются.
//
// Параметры:
//   Задачи - Массив из ЗадачаСсылка.ЗадачаИсполнителя
//          - ЗадачаСсылка.ЗадачаИсполнителя
//
Процедура ЗаблокироватьЗадачи(Задачи) Экспорт
	
	Блокировка = Новый БлокировкаДанных;
	Если ТипЗнч(Задачи) = Тип("Массив") Тогда
		Для каждого Задача Из Задачи Цикл
			
			Если ТипЗнч(Задача) = Тип("СтрокаГруппировкиДинамическогоСписка") Тогда 
				Продолжить;
			КонецЕсли;
			
			ЭлементБлокировки = Блокировка.Добавить("Задача.ЗадачаИсполнителя");
			ЭлементБлокировки.УстановитьЗначение("Ссылка", Задача);
		КонецЦикла;
	Иначе	
		Если ТипЗнч(БизнесПроцессы) = Тип("СтрокаГруппировкиДинамическогоСписка") Тогда
			Возврат;
		КонецЕсли;	
		ЭлементБлокировки = Блокировка.Добавить("Задача.ЗадачаИсполнителя");
		ЭлементБлокировки.УстановитьЗначение("Ссылка", Задачи);
	КонецЕсли;
	Блокировка.Заблокировать();
	
КонецПроцедуры

// Заполняет реквизит ГлавнаяЗадача при создании бизнес-процесса на основании другого бизнес-процесса.
// См. также БизнесПроцессыИЗадачиПереопределяемый.ПриЗаполненииГлавнойЗадачиБизнесПроцесса.
//
// Параметры:
//  БизнесПроцессОбъект	 - ОпределяемыйТип.БизнесПроцессОбъект
//  ДанныеЗаполнения	 - ЗадачаСсылка
//                  	 - Произвольный - данные заполнения, которые передаются в обработчик заполнения.
//
Процедура ЗаполнитьГлавнуюЗадачу(БизнесПроцессОбъект, ДанныеЗаполнения) Экспорт
	
	СтандартнаяОбработка = Истина;
	БизнесПроцессыИЗадачиПереопределяемый.ПриЗаполненииГлавнойЗадачиБизнесПроцесса(БизнесПроцессОбъект, ДанныеЗаполнения, СтандартнаяОбработка);
	Если Не СтандартнаяОбработка Тогда
		Возврат;
	КонецЕсли;
	
	Если ДанныеЗаполнения = Неопределено Тогда 
		Возврат;
	КонецЕсли;
	
	Если ТипЗнч(ДанныеЗаполнения) = Тип("ЗадачаСсылка.ЗадачаИсполнителя") Тогда
		БизнесПроцессОбъект.ГлавнаяЗадача = ДанныеЗаполнения;
	КонецЕсли;
	
КонецПроцедуры

// Получить группу исполнителей задач, которая соответствует реквизитам адресации.
//  Если группа еще не существует, то создается и возвращается новая.
//
// Параметры:
//  РольИсполнителя               - СправочникСсылка.РолиИсполнителей - роль исполнителя.
//  ОсновнойОбъектАдресации       - Характеристика.ОбъектыАдресацииЗадач - ссылка на основной объект адресации.
//  ДополнительныйОбъектАдресации - Характеристика.ОбъектыАдресацииЗадач - ссылка на дополнительный объект адресации.
// 
// Возвращаемое значение:
//  СправочникСсылка.ГруппыИсполнителейЗадач
//
Функция ГруппаИсполнителейЗадач(РольИсполнителя, ОсновнойОбъектАдресации, ДополнительныйОбъектАдресации) Экспорт
	
	НачатьТранзакцию();
	Попытка
		
		Запрос = Новый Запрос(
			"ВЫБРАТЬ ПЕРВЫЕ 1
			|	ГруппыИсполнителейЗадач.Ссылка КАК Ссылка
			|ИЗ
			|	Справочник.ГруппыИсполнителейЗадач КАК ГруппыИсполнителейЗадач
			|ГДЕ
			|	ГруппыИсполнителейЗадач.РольИсполнителя = &РольИсполнителя
			|	И ГруппыИсполнителейЗадач.ОсновнойОбъектАдресации = &ОсновнойОбъектАдресации
			|	И ГруппыИсполнителейЗадач.ДополнительныйОбъектАдресации = &ДополнительныйОбъектАдресации");
			
		Запрос.УстановитьПараметр("РольИсполнителя",               РольИсполнителя);
		Запрос.УстановитьПараметр("ОсновнойОбъектАдресации",       ОсновнойОбъектАдресации);
		Запрос.УстановитьПараметр("ДополнительныйОбъектАдресации", ДополнительныйОбъектАдресации);
		
		Выборка = Запрос.Выполнить().Выбрать();
		Если Выборка.Следующий() Тогда
			ГруппаИсполнителей = Выборка.Ссылка;
		Иначе
		
			Блокировка = Новый БлокировкаДанных;
			ЭлементБлокировки = Блокировка.Добавить("Справочник.ГруппыИсполнителейЗадач");
			ЭлементБлокировки.УстановитьЗначение("РольИсполнителя",               РольИсполнителя);
			ЭлементБлокировки.УстановитьЗначение("ОсновнойОбъектАдресации",       ОсновнойОбъектАдресации);
			ЭлементБлокировки.УстановитьЗначение("ДополнительныйОбъектАдресации", ДополнительныйОбъектАдресации);
			Блокировка.Заблокировать();
			
			Выборка = Запрос.Выполнить().Выбрать(); // Ответственное чтение данных
			Если Выборка.Следующий() Тогда
				
				ГруппаИсполнителей = Выборка.Ссылка;
			
			Иначе
				
				// Требуется добавить новую группу исполнителей задач.
				ГруппаИсполнителейОбъект = Справочники.ГруппыИсполнителейЗадач.СоздатьЭлемент();
				ГруппаИсполнителейОбъект.РольИсполнителя               = РольИсполнителя;
				ГруппаИсполнителейОбъект.ОсновнойОбъектАдресации       = ОсновнойОбъектАдресации;
				ГруппаИсполнителейОбъект.ДополнительныйОбъектАдресации = ДополнительныйОбъектАдресации;
				ГруппаИсполнителейОбъект.Записать();
				ГруппаИсполнителей = ГруппаИсполнителейОбъект.Ссылка;
				
			КонецЕсли;
			
		КонецЕсли;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
	Возврат ГруппаИсполнителей;
	
КонецФункции 

////////////////////////////////////////////////////////////////////////////////
// Отложенный старт бизнес-процессов.

// Добавляет процесс в очередь для отложенного старта.
//
// Параметры:
//  Процесс    - ОпределяемыйТип.БизнесПроцесс
//  ДатаСтарта - Дата - дата отложенного старта.
//
Процедура ДобавитьПроцессДляОтложенногоСтарта(Процесс, ДатаСтарта) Экспорт
	
	Если Не ЗначениеЗаполнено(ДатаСтарта) ИЛИ Не ЗначениеЗаполнено(Процесс) Тогда
		Возврат;
	КонецЕсли;
	
	НаборЗаписей = РегистрыСведений.ПроцессыДляЗапуска.СоздатьНаборЗаписей();
	НаборЗаписей.Отбор.Владелец.Установить(Процесс);
	
	Запись = НаборЗаписей.Добавить();
	Запись.Владелец = Процесс;
	Запись.ДатаОтложенногоСтарта = ДатаСтарта;
	Запись.Состояние = Перечисления.СостоянияПроцессовДляЗапуска.ГотовКСтарту;
	
	НаборЗаписей.Записать();
	
КонецПроцедуры

// Отключает отложенный старт процесса.
//
// Параметры:
//  Процесс - ОпределяемыйТип.БизнесПроцесс
//
Процедура ОтключитьОтложенныйСтартПроцесса(Процесс) Экспорт
	
	НастройкаСтарта = ПараметрыОтложенногоПроцесса(Процесс);
	
	Если НастройкаСтарта = Неопределено Тогда // Процесс не ожидает старта.
		Возврат;
	КонецЕсли;
	
	Если НастройкаСтарта.Состояние = ПредопределенноеЗначение("Перечисление.СостоянияПроцессовДляЗапуска.ГотовКСтарту") Тогда
		НаборЗаписей = РегистрыСведений.ПроцессыДляЗапуска.СоздатьНаборЗаписей();
		НаборЗаписей.Отбор.Владелец.Установить(Процесс);
		НаборЗаписей.Записать();
	КонецЕсли;
	
КонецПроцедуры

// Стартует отложенный бизнес-процесс, устанавливая признак старта.
//
// Параметры:
//   БизнесПроцесс - ОпределяемыйТип.БизнесПроцесс
//
Процедура СтартоватьОтложенныйПроцесс(БизнесПроцесс) Экспорт
	
	НачатьТранзакцию();
	
	Попытка
		
		ЗаблокироватьДанныеДляРедактирования(БизнесПроцесс);
		
		БизнесПроцессОбъект = БизнесПроцесс.ПолучитьОбъект();
		// Стартуем бизнес процесс и регистрируем этот старт в регистре.
		БизнесПроцессОбъект.Старт();
		РегистрыСведений.ПроцессыДляЗапуска.ЗарегистрироватьСтартПроцесса(БизнесПроцесс);
		
		РазблокироватьДанныеДляРедактирования(БизнесПроцесс);
		
		ЗафиксироватьТранзакцию();
		
	Исключение
		
		ОтменитьТранзакцию();
		Описание = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Не удалось отложенно запустить процесс по причине:
			|%1
			|Попробуйте запустить процесс вручную, а не отложенно.'"),
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		РегистрыСведений.ПроцессыДляЗапуска.ЗарегистрироватьОтменуСтарта(БизнесПроцесс, Описание);
			
	КонецПопытки;
	
КонецПроцедуры

// Возвращает сведения о запуске для процесса.
//
// Параметры:
//  Процесс - ОпределяемыйТип.БизнесПроцесс
// 
// Возвращаемое значение:
//  - Неопределено - если сведений нет.
//  - Структура:
//     * БизнесПроцесс - ОпределяемыйТип.БизнесПроцесс.
//     * ДатаОтложенногоСтарта - Дата
//     * Состояние - ПеречислениеСсылка.СостоянияПроцессовДляЗапуска.
//     * ПричинаОтменыСтарта - Строка - причина отмены старта.
//
Функция ПараметрыОтложенногоПроцесса(Процесс) Экспорт
	
	Результат = Неопределено;
	
	Если Не ЗначениеЗаполнено(Процесс) Тогда
		Возврат Результат;
	КонецЕсли;
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	ПроцессыДляЗапуска.Владелец,
		|	ПроцессыДляЗапуска.ДатаОтложенногоСтарта,
		|	ПроцессыДляЗапуска.Состояние,
		|	ПроцессыДляЗапуска.ПричинаОтменыСтарта
		|ИЗ
		|	РегистрСведений.ПроцессыДляЗапуска КАК ПроцессыДляЗапуска
		|ГДЕ
		|	ПроцессыДляЗапуска.Владелец = &БизнесПроцесс";
	Запрос.УстановитьПараметр("БизнесПроцесс", Процесс);
	Выборка = Запрос.Выполнить().Выбрать();
	
	Если Выборка.Следующий() Тогда
		Результат = Новый Структура;
		Результат.Вставить("БизнесПроцесс", Выборка.Владелец);
		Результат.Вставить("ДатаОтложенногоСтарта", Выборка.ДатаОтложенногоСтарта);
		Результат.Вставить("Состояние", Выборка.Состояние);
		Результат.Вставить("ПричинаОтменыСтарта", Выборка.ПричинаОтменыСтарта);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Возвращает дату старта отложенного бизнес-процесса в том случае, когда БизнесПроцесс
// ожидает отложенного старта. В противном случае возвращает пустую дату.
//
// Параметры:
//  БизнесПроцесс - ОпределяемыйТип.БизнесПроцесс
// 
// Возвращаемое значение:
//  Дата
//
Функция ДатаОтложенногоСтартаПроцесса(БизнесПроцесс) Экспорт

	ДатаОтложенногоСтарта = '00010101';
	
	Настройка = ПараметрыОтложенногоПроцесса(БизнесПроцесс);
	
	Если Настройка = Неопределено Тогда
		Возврат ДатаОтложенногоСтарта;
	КонецЕсли;
	
	Если Настройка.Состояние = ПредопределенноеЗначение("Перечисление.СостоянияПроцессовДляЗапуска.ГотовКСтарту") Тогда
		ДатаОтложенногоСтарта = Настройка.ДатаОтложенногоСтарта;
	КонецЕсли;
	
	Возврат ДатаОтложенногоСтарта;

КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Обработчики регламентных заданий.

// Выполняет рассылку уведомлений исполнителям о новых задачах за период с момента предыдущей рассылки.
// Рассылка выполняется по почте от системной учетной записи.
// Также является обработчиком регламентного задания УведомлениеИсполнителейОНовыхЗадачах.
//
Процедура УведомитьИсполнителейОНовыхЗадачах() Экспорт
	
	ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(Метаданные.РегламентныеЗадания.УведомлениеИсполнителейОНовыхЗадачах);
	
	ОписаниеОшибки = "";
	ВидСообщения = НСтр("ru = 'Бизнес-процессы и задачи.Уведомление о новых задачах'", ОбщегоНазначения.КодОсновногоЯзыка());

	Если НЕ СистемнаяУчетнаяЗаписьНастроена(ОписаниеОшибки) Тогда
		ЗаписьЖурналаРегистрации(ВидСообщения, УровеньЖурналаРегистрации.Ошибка,
			Метаданные.РегламентныеЗадания.УведомлениеИсполнителейОНовыхЗадачах,, ОписаниеОшибки);
		Возврат;
	КонецЕсли;
	
	ДатаУведомления = ТекущаяДатаСеанса();
	ДатаПоследнегоУведомления = Константы.ДатаУведомленияОНовыхЗадачах.Получить();
	
	// Если оповещение ранее не производилось, или последнее оповещение происходило
	// ранее, чем за сутки, то отбираем новые задачи за последние сутки.
	Если (ДатаПоследнегоУведомления = '00010101000000') 
		Или (ДатаУведомления - ДатаПоследнегоУведомления > 24*60*60) Тогда
		ДатаПоследнегоУведомления = ДатаУведомления - 24*60*60;
	КонецЕсли;
	
	ЗаписьЖурналаРегистрации(ВидСообщения, УровеньЖурналаРегистрации.Информация,,,
		СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Начато регламентное уведомление о новых задачах за период %1 - %2'"),
		ДатаПоследнегоУведомления, ДатаУведомления));
	
	ЗадачиПоИсполнителям = ВыбратьНовыеЗадачиПоИсполнителям(ДатаПоследнегоУведомления, ДатаУведомления);
	Получатели = ОбщегоНазначенияКлиентСервер.СвернутьМассив(ЗадачиПоИсполнителям.Строки.ВыгрузитьКолонку("Исполнитель"));
	АдресаПолучателей = АдресаЭлектроннойПочты(Получатели);
	Для Каждого СтрокаИсполнителя Из ЗадачиПоИсполнителям.Строки Цикл
		ОтправитьУведомлениеОНовыхЗадачах(СтрокаИсполнителя.Исполнитель, СтрокаИсполнителя, АдресаПолучателей);
	КонецЦикла;
	
	УстановитьПривилегированныйРежим(Истина);
	Константы.ДатаУведомленияОНовыхЗадачах.Установить(ДатаУведомления);
	УстановитьПривилегированныйРежим(Ложь);
	
	ЗаписьЖурналаРегистрации(ВидСообщения, УровеньЖурналаРегистрации.Информация,,,
		СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Завершено регламентное уведомление о новых задачах (уведомлено исполнителей: %1)'"),
		ЗадачиПоИсполнителям.Строки.Количество()));
	
КонецПроцедуры

// Выполняет рассылку уведомлений исполнителям и авторам задач о задачах, не выполненных в срок.
// Рассылка выполняется по почте от системной учетной записи.
// Если задача направлена "в никуда", т.е. роли с пустым списком исполнителей,
// то создается новая задача ответственным за настройку ролей.
//
// Также является обработчиком регламентного задания МониторингЗадач.
//
Процедура ПроконтролироватьЗадачи() Экспорт
	
	ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(Метаданные.РегламентныеЗадания.МониторингЗадач);
	ОписаниеОшибки = "";
	
	Если НЕ СистемнаяУчетнаяЗаписьНастроена(ОписаниеОшибки) Тогда
		ВидСообщения = НСтр("ru = 'Бизнес-процессы и задачи.Мониторинг задач'", ОбщегоНазначения.КодОсновногоЯзыка());
		ЗаписьЖурналаРегистрации(ВидСообщения, УровеньЖурналаРегистрации.Ошибка,
			Метаданные.РегламентныеЗадания.МониторингЗадач,, ОписаниеОшибки);
			Возврат;
	КонецЕсли;

	ПросроченныеЗадачи = ВыбратьПросроченныеЗадачи();
	Если ПросроченныеЗадачи.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
		
	ПисьмаОПросроченныхЗадачах = ПисьмаОПросроченныхЗадачах(ПросроченныеЗадачи);
	Для Каждого Письмо Из ПисьмаОПросроченныхЗадачах Цикл
		ОтправитьУведомлениеОПросроченноеЗадаче(Письмо);
	КонецЦикла;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Обновление информационной базы.

// Подготовить первую порцию объектов для отложенной обработки прав доступа.
// Для вызова из отложенных обработчиков обновления при изменении логики формирования наборов значений доступа.
//
// Параметры:
//   Параметры     - Структура - структура параметров отложенного обработчика обновления.
//   БизнесПроцесс - ОбъектМетаданныхБизнесПроцесс  - метаданные бизнес-процесса, наборы значений доступа
//                   которого требуется обновить.
//   ИмяПроцедуры  - Строка - имя процедуры отложенного обработчика обновления для журнала регистрации.
//   РазмерПорции  - Число  - количество объектов, обрабатываемых за один вызов.
//
Процедура НачатьОбновлениеПорцииНаборовЗначенийДоступа(Параметры, БизнесПроцесс, ИмяПроцедуры, РазмерПорции = 1000) Экспорт
	
	Если Параметры.ПрогрессВыполнения.ВсегоОбъектов = 0 Тогда
		Запрос = Новый Запрос;
		Запрос.Текст =
			"ВЫБРАТЬ
			|	КОЛИЧЕСТВО(ТаблицаСНаборамиЗначенийДоступа.Ссылка) КАК Количество,
			|	МАКСИМУМ(ТаблицаСНаборамиЗначенийДоступа.Дата) КАК Дата
			|ИЗ
			|	#Таблица КАК ТаблицаСНаборамиЗначенийДоступа";
		
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "#Таблица", БизнесПроцесс.ПолноеИмя());
		РезультатЗапроса = Запрос.Выполнить().Выгрузить();
		Параметры.ПрогрессВыполнения.ВсегоОбъектов = РезультатЗапроса[0].Количество;
		
		Если Не Параметры.Свойство("НачальнаяДатаКОбработке") Тогда
			Параметры.Вставить("НачальнаяДатаКОбработке", РезультатЗапроса[0].Дата);
		КонецЕсли;
		
	КонецЕсли;
	
	Если Не Параметры.Свойство("ПроблемныеОбъекты") Тогда
		Параметры.Вставить("ПроблемныеОбъекты", Новый Массив);
	КонецЕсли;
	
	Если Не Параметры.Свойство("НачальнаяСсылкаКОбработке") Тогда
		Параметры.Вставить("НачальнаяСсылкаКОбработке", ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(БизнесПроцесс.ПолноеИмя()).ПустаяСсылка());
	КонецЕсли;
	
	Запрос = Новый Запрос;
	Запрос.Текст =
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	ТаблицаСНаборамиЗначенийДоступа.Ссылка КАК Ссылка,
		|	ТаблицаСНаборамиЗначенийДоступа.Дата КАК Дата
		|ИЗ
		|	#Таблица КАК ТаблицаСНаборамиЗначенийДоступа
		|ГДЕ ТаблицаСНаборамиЗначенийДоступа.Дата <= &НачальнаяДатаКОбработке
		|   И ТаблицаСНаборамиЗначенийДоступа.Ссылка > &НачальнаяСсылкаКОбработке
		|УПОРЯДОЧИТЬ ПО 
		|   Дата УБЫВ,
		|   Ссылка";
	
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "ВЫБРАТЬ ПЕРВЫЕ 1", "ВЫБРАТЬ ПЕРВЫЕ " + Формат(РазмерПорции, "ЧГ=0")); //@Query-part-1, @Query-part-2
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "#Таблица", БизнесПроцесс.ПолноеИмя());
	Запрос.УстановитьПараметр("НачальнаяДатаКОбработке", Параметры.НачальнаяДатаКОбработке);
	Запрос.УстановитьПараметр("НачальнаяСсылкаКОбработке", Параметры.НачальнаяСсылкаКОбработке);
	
	РезультатЗапроса = Запрос.Выполнить().Выгрузить();
	ОбъектыКОбработке = РезультатЗапроса.ВыгрузитьКолонку("Ссылка");
	Параметры.Вставить("ОбъектыКОбработке", ОбъектыКОбработке);
	
	ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Параметры.ОбъектыКОбработке, Параметры.ПроблемныеОбъекты);
	Параметры.ПроблемныеОбъекты.Очистить();
	
	Параметры.ОбработкаЗавершена = ОбъектыКОбработке.Количество() = 0 
		Или РезультатЗапроса[0].Ссылка = Параметры.НачальнаяСсылкаКОбработке;
	Если Не Параметры.ОбработкаЗавершена Тогда
		
		Если Не Параметры.Свойство("БизнесПроцесс") Тогда
			Параметры.Вставить("БизнесПроцесс", БизнесПроцесс);
		КонецЕсли;
		
		Если Не Параметры.Свойство("ОбъектовОбработано") Тогда
			Параметры.Вставить("ОбъектовОбработано", 0);
		КонецЕсли;
		
		Если Не Параметры.Свойство("ИмяПроцедуры") Тогда
			Параметры.Вставить("ИмяПроцедуры", ИмяПроцедуры);
		КонецЕсли;
		
		Параметры.НачальнаяДатаКОбработке = РезультатЗапроса[РезультатЗапроса.Количество() - 1].Дата;
		Параметры.НачальнаяСсылкаКОбработке = РезультатЗапроса[РезультатЗапроса.Количество() - 1].Ссылка;
	КонецЕсли;
	
КонецПроцедуры

// Завершить обработку первой порции объектов для отложенной обработки прав доступа.
// Для вызова из отложенных обработчиков обновления при изменении логики формирования наборов значений доступа.
//
// Параметры:
//   Параметры - Структура - параметры отложенного обработчика обновления.
//
Процедура ЗавершитьОбновлениеПорцииНаборовЗначенийДоступа(Параметры) Экспорт
	
	Параметры.ПрогрессВыполнения.ОбработаноОбъектов = Параметры.ПрогрессВыполнения.ОбработаноОбъектов + Параметры.ОбъектовОбработано;
	Если Параметры.ОбъектовОбработано = 0 Тогда
		ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Процедуре ""%1"" не удалось обновить права доступа для некоторых объектов (пропущены): %2'"),
				Параметры.ИмяПроцедуры, Параметры.ПроблемныеОбъекты.Количество());
		ВызватьИсключение ТекстСообщения;
	КонецЕсли;
	
	ЗаписьЖурналаРегистрации(ОбновлениеИнформационнойБазы.СобытиеЖурналаРегистрации(), УровеньЖурналаРегистрации.Информация,
		Параметры.БизнесПроцесс,, 
		СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Процедура ""%1"" обновила права доступа для очередной порции объектов: %2'"), 
			Параметры.ИмяПроцедуры, Параметры.ОбъектовОбработано));
	
	// Очистка временных параметров, которые не нужно сохранять между сеансами.
	Параметры.Удалить("ОбъектыКОбработке");
	Параметры.Удалить("ИмяПроцедуры");
	Параметры.Удалить("БизнесПроцесс");
	Параметры.Удалить("ОбъектовОбработано");
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныйПрограммныйИнтерфейс

////////////////////////////////////////////////////////////////////////////////
// Обработчики событий подсистем конфигурации.

// См. ОбновлениеИнформационнойБазыБСП.ПриДобавленииОбработчиковОбновления.
Процедура ПриДобавленииОбработчиковОбновления(Обработчики) Экспорт
	
	Обработчик = Обработчики.Добавить();
	Обработчик.Версия = "1.0.2.2";
	Обработчик.НачальноеЗаполнение = Истина;
	Обработчик.Процедура = "БизнесПроцессыИЗадачиСервер.ЗаполнитьОтветственногоЗаКонтрольИсполнения";
	
	Обработчик = Обработчики.Добавить();
	Обработчик.НачальноеЗаполнение = Истина;
	Обработчик.Версия              = "2.3.3.70";
	Обработчик.Процедура           = "БизнесПроцессыИЗадачиСервер.ОбновитьИспользованиеРегламентныхЗаданий";
	Обработчик.ОбщиеДанные         = Ложь;
	Обработчик.РежимВыполнения     = "Оперативно";
	
	Обработчик = Обработчики.Добавить();
	Обработчик.НачальноеЗаполнение = Истина;
	Обработчик.РежимВыполнения = "Оперативно";
	Обработчик.Процедура = "БизнесПроцессыИЗадачиСервер.ЗаполнитьНаименованиеПредопределенногоЭлементаВсеОбъектыАдресации";
	
	Обработчик = Обработчики.Добавить();
	Обработчик.Процедура = "РегистрыСведений.ДанныеБизнесПроцессов.ОбработатьДанныеДляПереходаНаНовуюВерсию";
	Обработчик.Версия = "3.1.9.99";
	Обработчик.РежимВыполнения = "Отложенно";
	Обработчик.Идентификатор = Новый УникальныйИдентификатор("5137a43e-75aa-4a68-ba2f-525a3a646de8");
	Обработчик.Многопоточный = Истина;
	Обработчик.ПроцедураЗаполненияДанныхОбновления = "РегистрыСведений.ДанныеБизнесПроцессов.ЗарегистрироватьДанныеКОбработкеДляПереходаНаНовуюВерсию";
	Обработчик.ПроцедураПроверки = "ОбновлениеИнформационнойБазы.ДанныеОбновленыНаНовуюВерсиюПрограммы";
	Обработчик.Комментарий = НСтр("ru = 'Заполнение реквизита Состояние в регистре Бизнес-процессы.'");
	Обработчик.ИзменяемыеОбъекты = Метаданные.РегистрыСведений.ДанныеБизнесПроцессов.ПолноеИмя();
	Обработчик.БлокируемыеОбъекты = Метаданные.РегистрыСведений.ДанныеБизнесПроцессов.ПолноеИмя();

	Читаемые = Новый Массив;
	ТипыБизнесПроцессов = Метаданные.ОпределяемыеТипы.БизнесПроцесс.Тип;
	Если Не ТипыБизнесПроцессов.СодержитТип(Тип("Строка")) Тогда
		Для каждого ТипБизнесПроцесса Из ТипыБизнесПроцессов.Типы() Цикл 
			Читаемые.Добавить(Метаданные.НайтиПоТипу(ТипБизнесПроцесса).ПолноеИмя());
		КонецЦикла;	
	КонецЕсли;
	Читаемые.Добавить(Метаданные.РегистрыСведений.ДанныеБизнесПроцессов.ПолноеИмя());
	Обработчик.ЧитаемыеОбъекты = СтрСоединить(Читаемые, ",");
	
КонецПроцедуры

// См. ИнтеграцияПодсистемБСП.ПриОпределенииГруппИсполнителей.
Процедура ПриОпределенииГруппИсполнителей(МенеджерВременныхТаблиц, СодержаниеПараметра, ЗначениеПараметра, НетГруппИсполнителей) Экспорт
	
	НетГруппИсполнителей = Ложь;
	
	Запрос = Новый Запрос;
	Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
	
	Если СодержаниеПараметра = "ГруппыИсполнителей" Тогда
		
		Запрос.УстановитьПараметр("ГруппыИсполнителей", ЗначениеПараметра);
		Запрос.Текст =
		"ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	ИсполнителиЗадач.ГруппаИсполнителейЗадач КАК ГруппаИсполнителей,
		|	ИсполнителиЗадач.Исполнитель КАК Пользователь
		|ПОМЕСТИТЬ ТаблицаГруппИсполнителей
		|ИЗ
		|	РегистрСведений.ИсполнителиЗадач КАК ИсполнителиЗадач
		|ГДЕ
		|	ИсполнителиЗадач.ГруппаИсполнителейЗадач В(&ГруппыИсполнителей)";
		
	ИначеЕсли СодержаниеПараметра = "Исполнители" Тогда
		
		Запрос.УстановитьПараметр("Исполнители", ЗначениеПараметра);
		Запрос.Текст =
		"ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	ИсполнителиЗадач.ГруппаИсполнителейЗадач КАК ГруппаИсполнителей,
		|	ИсполнителиЗадач.Исполнитель КАК Пользователь
		|ПОМЕСТИТЬ ТаблицаГруппИсполнителей
		|ИЗ
		|	РегистрСведений.ИсполнителиЗадач КАК ИсполнителиЗадач
		|ГДЕ
		|	ИсполнителиЗадач.Исполнитель В(&Исполнители)";
		
	Иначе
		Запрос.Текст =
		"ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	ИсполнителиЗадач.ГруппаИсполнителейЗадач КАК ГруппаИсполнителей,
		|	ИсполнителиЗадач.Исполнитель КАК Пользователь
		|ПОМЕСТИТЬ ТаблицаГруппИсполнителей
		|ИЗ
		|	РегистрСведений.ИсполнителиЗадач КАК ИсполнителиЗадач";
	КонецЕсли;
	
	Запрос.Выполнить();
	
КонецПроцедуры

// См. ЗагрузкаДанныхИзФайлаПереопределяемый.ПриОпределенииСправочниковДляЗагрузкиДанных.
Процедура ПриОпределенииСправочниковДляЗагрузкиДанных(ЗагружаемыеСправочники) Экспорт
	
	// Загрузка в справочник ГруппыИсполнителейЗадач запрещена.
	СтрокаТаблицы = ЗагружаемыеСправочники.Найти(Метаданные.Справочники.ГруппыИсполнителейЗадач.ПолноеИмя(), "ПолноеИмя");
	Если СтрокаТаблицы <> Неопределено Тогда 
		ЗагружаемыеСправочники.Удалить(СтрокаТаблицы);
	КонецЕсли;
	
КонецПроцедуры

// См. ГрупповоеИзменениеОбъектовПереопределяемый.ПриОпределенииОбъектовСРедактируемымиРеквизитами.
Процедура ПриОпределенииОбъектовСРедактируемымиРеквизитами(Объекты) Экспорт
	Объекты.Вставить(Метаданные.БизнесПроцессы.Задание.ПолноеИмя(), "РеквизитыРедактируемыеВГрупповойОбработке");
	Объекты.Вставить(Метаданные.Задачи.ЗадачаИсполнителя.ПолноеИмя(), "РеквизитыРедактируемыеВГрупповойОбработке");
	Объекты.Вставить(Метаданные.ПланыВидовХарактеристик.ОбъектыАдресацииЗадач.ПолноеИмя(), "РеквизитыНеРедактируемыеВГрупповойОбработке");
	Объекты.Вставить(Метаданные.Справочники.ГруппыИсполнителейЗадач.ПолноеИмя(), "РеквизитыНеРедактируемыеВГрупповойОбработке");
	Объекты.Вставить(Метаданные.Справочники.РолиИсполнителей.ПолноеИмя(), "РеквизитыНеРедактируемыеВГрупповойОбработке");
КонецПроцедуры

// См. РегламентныеЗаданияПереопределяемый.ПриОпределенииНастроекРегламентныхЗаданий
Процедура ПриОпределенииНастроекРегламентныхЗаданий(Настройки) Экспорт
	Настройка = Настройки.Добавить();
	Настройка.РегламентноеЗадание = Метаданные.РегламентныеЗадания.МониторингЗадач;
	Настройка.ФункциональнаяОпция = Метаданные.ФункциональныеОпции.ИспользоватьБизнесПроцессыИЗадачи;
	Настройка.РаботаетСВнешнимиРесурсами = Истина;
	
	Настройка = Настройки.Добавить();
	Настройка.РегламентноеЗадание = Метаданные.РегламентныеЗадания.УведомлениеИсполнителейОНовыхЗадачах;
	Настройка.ФункциональнаяОпция = Метаданные.ФункциональныеОпции.ИспользоватьБизнесПроцессыИЗадачи;
	Настройка.РаботаетСВнешнимиРесурсами = Истина;
	Настройка.ВключатьПриВключенииФункциональнойОпции = Ложь;
	
	Настройка = Настройки.Добавить();
	Настройка.РегламентноеЗадание = Метаданные.РегламентныеЗадания.СтартОтложенныхПроцессов;
	Настройка.ФункциональнаяОпция = Метаданные.ФункциональныеОпции.ИспользоватьБизнесПроцессыИЗадачи;

КонецПроцедуры

// См. ОбщегоНазначенияПереопределяемый.ПриДобавленииИсключенийПоискаСсылок.
Процедура ПриДобавленииИсключенийПоискаСсылок(ИсключенияПоискаСсылок) Экспорт
	
	ИсключенияПоискаСсылок.Добавить(Метаданные.РегистрыСведений.ИсполнителиЗадач.ПолноеИмя());
	ИсключенияПоискаСсылок.Добавить(Метаданные.РегистрыСведений.ДанныеБизнесПроцессов.ПолноеИмя());
	
КонецПроцедуры

// См. ОчередьЗаданийПереопределяемый.ПриПолученииСпискаШаблонов
Процедура ПриПолученииСпискаШаблонов(ШаблоныЗаданий) Экспорт
	
	ШаблоныЗаданий.Добавить(Метаданные.РегламентныеЗадания.МониторингЗадач.Имя);
	ШаблоныЗаданий.Добавить(Метаданные.РегламентныеЗадания.УведомлениеИсполнителейОНовыхЗадачах.Имя);
	
КонецПроцедуры

// См. НапоминанияПользователяПереопределяемый.ПриЗаполненииСпискаРеквизитовИсточникаСДатамиДляНапоминания.
Процедура ПриЗаполненииСпискаРеквизитовИсточникаСДатамиДляНапоминания(Источник, РеквизитыСДатами) Экспорт
	
	Если ТипЗнч(Источник) = Тип("ЗадачаСсылка.ЗадачаИсполнителя") Тогда
		РеквизитыСДатами.Очистить();
		РеквизитыСДатами.Добавить("СрокИсполнения"); 
		РеквизитыСДатами.Добавить("ДатаНачала"); 
	КонецЕсли;
	
КонецПроцедуры

// См. УправлениеДоступомПереопределяемый.ПриЗаполненииЗависимостейПравДоступа.
Процедура ПриЗаполненииЗависимостейПравДоступа(ЗависимостиПрав) Экспорт
	
	// Задача исполнителя может быть изменена, когда бизнес-процесс доступен только для чтения,
	// поэтому проверка права изменения и ограничения изменения не требуется,
	// а требуется более "мягкое" условие - проверка права и ограничения чтения.
	
	Строка = ЗависимостиПрав.Добавить();
	Строка.ПодчиненнаяТаблица = "Задача.ЗадачаИсполнителя";
	Строка.ВедущаяТаблица     = "БизнесПроцесс.Задание";
	
КонецПроцедуры

// См. УправлениеДоступомПереопределяемый.ПриЗаполненииВидовОграниченийПравОбъектовМетаданных.
Процедура ПриЗаполненииВидовОграниченийПравОбъектовМетаданных(Описание) Экспорт
	
	Описание = Описание 
		+ "
		|БизнесПроцесс.Задание.Чтение.Пользователи
		|БизнесПроцесс.Задание.Изменение.Пользователи
		|Задача.ЗадачаИсполнителя.Чтение.Объект.БизнесПроцесс.Задание
		|Задача.ЗадачаИсполнителя.Чтение.Пользователи
		|Задача.ЗадачаИсполнителя.Изменение.Пользователи
		|РегистрСведений.ДанныеБизнесПроцессов.Чтение.Объект.БизнесПроцесс.Задание
		|";
	
КонецПроцедуры

// См. УправлениеДоступомПереопределяемый.ПриЗаполненииВидовДоступа.
Процедура ПриЗаполненииВидовДоступа(ВидыДоступа) Экспорт
	
	ВидДоступа = ВидыДоступа.Найти("Пользователи", "Имя");
	Если ВидДоступа <> Неопределено Тогда
		МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
		МодульУправлениеДоступом.ДобавитьДополнительныеТипыВидаДоступа(ВидДоступа,
			Тип("СправочникСсылка.ГруппыИсполнителейЗадач"));
	КонецЕсли;
	
КонецПроцедуры

// См. УправлениеДоступомПереопределяемый.ПриЗаполненииСписковСОграничениемДоступа.
Процедура ПриЗаполненииСписковСОграничениемДоступа(Списки) Экспорт
	
	Списки.Вставить(Метаданные.РегистрыСведений.ДанныеБизнесПроцессов, Истина);
	Списки.Вставить(Метаданные.РегистрыСведений.ИсполнителиЗадач, Истина);
	Списки.Вставить(Метаданные.БизнесПроцессы.Задание, Истина);
	Списки.Вставить(Метаданные.Задачи.ЗадачаИсполнителя, Истина);
	
КонецПроцедуры

// См. ВариантыОтчетовПереопределяемый.НастроитьВариантыОтчетов.
Процедура ПриНастройкеВариантовОтчетов(Настройки) Экспорт
	МодульВариантыОтчетов = ОбщегоНазначения.ОбщийМодуль("ВариантыОтчетов");
	МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.БизнесПроцессы);
	МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.ЗависшиеЗадачи);
	МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.Задания);
	МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.Задачи);
	МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.ЗадачиИстекающиеНаДату);
	МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.ПросроченныеЗадачи);
КонецПроцедуры

// Параметры:
//   ТекущиеДела - см. ТекущиеДелаСервер.ТекущиеДела.
//
Процедура ПриЗаполненииСпискаТекущихДел(ТекущиеДела) Экспорт
	
	МодульТекущиеДелаСервер = ОбщегоНазначения.ОбщийМодуль("ТекущиеДелаСервер");
	Если Не ПравоДоступа("Редактирование", Метаданные.Задачи.ЗадачаИсполнителя)
		Или МодульТекущиеДелаСервер.ДелоОтключено("ЗадачиИсполнителя") Тогда
		Возврат;
	КонецЕсли;
	
	Если Не ПолучитьФункциональнуюОпцию("ИспользоватьБизнесПроцессыИЗадачи") Тогда
		Возврат;
	КонецЕсли;
	
	КоличествоЗадачИсполнителя = КоличествоЗадачИсполнителя();
	
	// Процедура вызывается только при наличии подсистемы "Текущие дела", поэтому здесь
	// не делается проверка существования подсистемы.
	Разделы = МодульТекущиеДелаСервер.РазделыДляОбъекта(Метаданные.Задачи.ЗадачаИсполнителя.ПолноеИмя());
	
	Если Пользователи.ЭтоСеансВнешнегоПользователя()
		И Разделы.Количество() = 0 Тогда
		Разделы.Добавить(Метаданные.Задачи.ЗадачаИсполнителя);
	КонецЕсли;
	
	Для Каждого Раздел Из Разделы Цикл
		
		ИдентификаторМоихЗадач = "ЗадачиИсполнителя" + СтрЗаменить(Раздел.ПолноеИмя(), ".", "");
		Дело = ТекущиеДела.Добавить();
		Дело.Идентификатор  = ИдентификаторМоихЗадач;
		Дело.ЕстьДела       = КоличествоЗадачИсполнителя.Всего > 0;
		Дело.Представление  = НСтр("ru = 'Мои задачи'");
		Дело.Количество     = КоличествоЗадачИсполнителя.Всего;
		Дело.Форма          = "Задача.ЗадачаИсполнителя.Форма.МоиЗадачи";
		ЗначениеОтбора		= Новый Структура("Выполнена", Ложь);
		Дело.ПараметрыФормы = Новый Структура("Отбор", ЗначениеОтбора);
		Дело.Владелец       = Раздел;
		
		Дело = ТекущиеДела.Добавить();
		Дело.Идентификатор  = "ЗадачиИсполнителяПросроченные";
		Дело.ЕстьДела       = КоличествоЗадачИсполнителя.Просроченные > 0;
		Дело.Представление  = НСтр("ru = 'просроченные'");
		Дело.Количество     = КоличествоЗадачИсполнителя.Просроченные;
		Дело.Важное         = Истина;
		Дело.Владелец       = ИдентификаторМоихЗадач; 
		
		Дело = ТекущиеДела.Добавить();
		Дело.Идентификатор  = "ЗадачиИсполнителяНаСегодня";
		Дело.ЕстьДела       = КоличествоЗадачИсполнителя.НаСегодня > 0;
		Дело.Представление  = НСтр("ru = 'сегодня'");
		Дело.Количество     = КоличествоЗадачИсполнителя.НаСегодня;
		Дело.Владелец       = ИдентификаторМоихЗадач; 

		Дело = ТекущиеДела.Добавить();
		Дело.Идентификатор  = "ЗадачиИсполнителяНаНеделю";
		Дело.ЕстьДела       = КоличествоЗадачИсполнителя.НаНеделю > 0;
		Дело.Представление  = НСтр("ru = 'на этой неделе'");
		Дело.Количество     = КоличествоЗадачИсполнителя.НаНеделю;
		Дело.Владелец       = ИдентификаторМоихЗадач; 

		Дело = ТекущиеДела.Добавить();
		Дело.Идентификатор  = "ЗадачиИсполнителяНаСледующуюНеделю";
		Дело.ЕстьДела       = КоличествоЗадачИсполнителя.НаСледующуюНеделю > 0;
		Дело.Представление  = НСтр("ru = 'на следующей неделе'");
		Дело.Количество     = КоличествоЗадачИсполнителя.НаСледующуюНеделю > 0;
		Дело.Владелец       = ИдентификаторМоихЗадач; 
	КонецЦикла;
	
КонецПроцедуры

// См. ОчередьЗаданийПереопределяемый.ПриОпределенииПсевдонимовОбработчиков.
Процедура ПриОпределенииПсевдонимовОбработчиков(СоответствиеИменПсевдонимам) Экспорт
	
	СоответствиеИменПсевдонимам.Вставить("БизнесПроцессыИЗадачиСобытия.СтартОтложенныхПроцессов");
	
КонецПроцедуры

// Смотри также ОбновлениеИнформационнойБазыПереопределяемый.ПриОпределенииНастроек
//
// Параметры:
//  Объекты - Массив из ОбъектМетаданных
//
Процедура ПриОпределенииОбъектовСНачальнымЗаполнением(Объекты) Экспорт
	
	Объекты.Добавить(Метаданные.Справочники.РолиИсполнителей);
	Объекты.Добавить(Метаданные.ПланыВидовХарактеристик.ОбъектыАдресацииЗадач);
	
КонецПроцедуры

// См. СозданиеНаОснованииПереопределяемый.ПриОпределенииОбъектовСКомандамиСозданияНаОсновании.
Процедура ПриОпределенииОбъектовСКомандамиСозданияНаОсновании(Объекты) Экспорт
	
	Объекты.Добавить(Метаданные.БизнесПроцессы.Задание);
	Объекты.Добавить(Метаданные.Задачи.ЗадачаИсполнителя);
	
КонецПроцедуры

// См. СозданиеНаОснованииПереопределяемый.ПриДобавленииКомандСозданияНаОсновании.
Процедура ПриДобавленииКомандСозданияНаОсновании(Объект, КомандыСозданияНаОсновании, Параметры, СтандартнаяОбработка) Экспорт
	
	Если Объект = Метаданные.Справочники["Пользователи"] Тогда
		БизнесПроцессы.Задание.ДобавитьКомандуСоздатьНаОсновании(КомандыСозданияНаОсновании);
	КонецЕсли;
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаСФайлами") Тогда
		Если Объект = Метаданные.Справочники["Файлы"] Тогда
			БизнесПроцессы.Задание.ДобавитьКомандуСоздатьНаОсновании(КомандыСозданияНаОсновании);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

////////////////////////////////////////////////////////////////////////////////
// Мониторинг и контроль исполнения.

Функция ВыгрузитьИсполнителей(ТекстЗапроса, ОсновнойОбъектАдресацииСсылка = Неопределено, 
	ДопОбъектАдресацииСсылка = Неопределено)
	
	Запрос = Новый Запрос(ТекстЗапроса);
	
	Если ЗначениеЗаполнено(ДопОбъектАдресацииСсылка) Тогда
		Запрос.УстановитьПараметр("ДОА", ДопОбъектАдресацииСсылка);
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ОсновнойОбъектАдресацииСсылка) Тогда
		Запрос.УстановитьПараметр("ООА", ОсновнойОбъектАдресацииСсылка);
	КонецЕсли;
	
	Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Исполнитель");
	
КонецФункции

Функция НайтиОтветственныхЗаНазначениеРолей(ОсновнойОбъектАдресации, ДополнительныйОбъектАдресации)
	
	ШаблонЗапроса = 
		"ВЫБРАТЬ РАЗЛИЧНЫЕ РАЗРЕШЕННЫЕ
		|	ИсполнителиЗадач.Исполнитель
		|ИЗ
		|	РегистрСведений.ИсполнителиЗадач КАК ИсполнителиЗадач
		|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.РолиИсполнителей КАК РолиИсполнителей
		|		ПО ИсполнителиЗадач.РольИсполнителя = РолиИсполнителей.Ссылка
		|ГДЕ
		|	РолиИсполнителей.Ссылка = ЗНАЧЕНИЕ(Справочник.РолиИсполнителей.ОтветственныйЗаКонтрольИсполнения)
		|	И &УсловиеПоОбъектамАдресации";
	
	Если ЗначениеЗаполнено(ДополнительныйОбъектАдресации) Тогда
		УсловиеПоОбъектамАдресации = "ИсполнителиЗадач.ОсновнойОбъектАдресации = &ООА
			|	И ИсполнителиЗадач.ДополнительныйОбъектАдресации = &ДОА"; // @Query-part
	ИначеЕсли ЗначениеЗаполнено(ОсновнойОбъектАдресации) Тогда
		УсловиеПоОбъектамАдресации =
			"ИсполнителиЗадач.ОсновнойОбъектАдресации = &ООА
			|	И (ИсполнителиЗадач.ДополнительныйОбъектАдресации = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ОбъектыАдресацииЗадач.ПустаяСсылка)
			|	ИЛИ ИсполнителиЗадач.ДополнительныйОбъектАдресации = Неопределено)"; // @Query-part
	Иначе
		УсловиеПоОбъектамАдресации =
			"(ИсполнителиЗадач.ОсновнойОбъектАдресации = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ОбъектыАдресацииЗадач.ПустаяСсылка)
			|		ИЛИ ИсполнителиЗадач.ОсновнойОбъектАдресации = Неопределено)
			|	И (ИсполнителиЗадач.ДополнительныйОбъектАдресации = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ОбъектыАдресацииЗадач.ПустаяСсылка)
			|		ИЛИ ИсполнителиЗадач.ДополнительныйОбъектАдресации = Неопределено)"; // @Query-part
	КонецЕсли;

	ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&УсловиеПоОбъектамАдресации", УсловиеПоОбъектамАдресации);
	Исполнители = ВыгрузитьИсполнителей(ТекстЗапроса, ОсновнойОбъектАдресации, ДополнительныйОбъектАдресации);
	
	// Если в задаче не заполнены основной и дополнительный объекты адресации.
	Если Не ЗначениеЗаполнено(ДополнительныйОбъектАдресации) И Не ЗначениеЗаполнено(ОсновнойОбъектАдресации) Тогда
		Возврат Исполнители;
	КонецЕсли;
	
	Если Исполнители.Количество() = 0 И ЗначениеЗаполнено(ДополнительныйОбъектАдресации) Тогда
		УсловиеПоОбъектамАдресации =
			"ИсполнителиЗадач.ОсновнойОбъектАдресации = &ООА
			|	И (ИсполнителиЗадач.ДополнительныйОбъектАдресации = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ОбъектыАдресацииЗадач.ПустаяСсылка)
			|	ИЛИ ИсполнителиЗадач.ДополнительныйОбъектАдресации = Неопределено)"; // @Query-part
		ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&УсловиеПоОбъектамАдресации", УсловиеПоОбъектамАдресации);
		Исполнители = ВыгрузитьИсполнителей(ТекстЗапроса, ОсновнойОбъектАдресации);
	КонецЕсли;
	
	Если Исполнители.Количество() = 0 Тогда
		УсловиеПоОбъектамАдресации =
			"(ИсполнителиЗадач.ОсновнойОбъектАдресации = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ОбъектыАдресацииЗадач.ПустаяСсылка)
			|		ИЛИ ИсполнителиЗадач.ОсновнойОбъектАдресации = Неопределено)
			|	И (ИсполнителиЗадач.ДополнительныйОбъектАдресации = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ОбъектыАдресацииЗадач.ПустаяСсылка)
			|		ИЛИ ИсполнителиЗадач.ДополнительныйОбъектАдресации = Неопределено)"; // @Query-part
		ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&УсловиеПоОбъектамАдресации", УсловиеПоОбъектамАдресации);
		Исполнители = ВыгрузитьИсполнителей(ТекстЗапроса);
	КонецЕсли;
	
	Возврат Исполнители;
	
КонецФункции

Функция ИсполнителиЗадач(Задачи)
	
	Результат = Новый Структура;
	Результат.Вставить("Исполнители", Новый Массив);
	Результат.Вставить("ПоЗадачам", Новый Соответствие);

	ТекстЗапроса = 
		"ВЫБРАТЬ РАЗЛИЧНЫЕ РАЗРЕШЕННЫЕ
		|	ЗадачаИсполнителя.Ссылка КАК Задача,
		|	ИсполнителиЗадач.Исполнитель КАК Исполнитель
		|ИЗ
		|	Задача.ЗадачаИсполнителя КАК ЗадачаИсполнителя
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИсполнителиЗадач КАК ИсполнителиЗадач
		|		ПО ИсполнителиЗадач.РольИсполнителя = ЗадачаИсполнителя.РольИсполнителя
		|		И ИсполнителиЗадач.ОсновнойОбъектАдресации = ЗадачаИсполнителя.ОсновнойОбъектАдресации
		|		И ИсполнителиЗадач.ДополнительныйОбъектАдресации = ЗадачаИсполнителя.ДополнительныйОбъектАдресации
		|ГДЕ
		|	ЗадачаИсполнителя.Ссылка В (&Задачи)
		|
		|УПОРЯДОЧИТЬ ПО
		|	ЗадачаИсполнителя.Ссылка";
		
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("Задачи", Задачи);
	ВыборкаЗапроса = Запрос.Выполнить().Выбрать();
	Пока ВыборкаЗапроса.Следующий() Цикл
		ИсполнителиЗадачи = Результат.ПоЗадачам[ВыборкаЗапроса.Задача];
		Если ИсполнителиЗадачи = Неопределено Тогда
			ИсполнителиЗадачи = Новый Массив;
			Результат.ПоЗадачам[ВыборкаЗапроса.Задача] = ИсполнителиЗадачи;
		КонецЕсли;
		Если ЗначениеЗаполнено(ВыборкаЗапроса.Исполнитель) Тогда
			ИсполнителиЗадачи.Добавить(ВыборкаЗапроса.Исполнитель);
			Результат.Исполнители.Добавить(ВыборкаЗапроса.Исполнитель);
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;
	
КонецФункции
	
Процедура НайтиПисьмоИДобавитьТекст(Знач НаборПисемПоАдресатам, Знач ПолучательПисьма,
	Знач ПредставлениеПолучателяПисьма, Знач ТекстПисьма, Знач ТипПисьма)
	
	ПараметрыОтбора = Новый Структура("ТипПисьма, ПочтовыйАдрес", ТипПисьма, ПолучательПисьма);
	СтрокаПараметрыПисьма = НаборПисемПоАдресатам.НайтиСтроки(ПараметрыОтбора);
	Если СтрокаПараметрыПисьма.Количество() = 0 Тогда
		СтрокаПараметрыПисьма = Неопределено;
	Иначе
		СтрокаПараметрыПисьма = СтрокаПараметрыПисьма[0];
	КонецЕсли;
	
	Если СтрокаПараметрыПисьма = Неопределено Тогда
		СтрокаПараметрыПисьма = НаборПисемПоАдресатам.Добавить();
		СтрокаПараметрыПисьма.ПочтовыйАдрес = ПолучательПисьма;
		СтрокаПараметрыПисьма.ТекстПисьма = "";
		СтрокаПараметрыПисьма.КоличествоЗадач = 0;
		СтрокаПараметрыПисьма.ТипПисьма = ТипПисьма;
		СтрокаПараметрыПисьма.Получатель = ПредставлениеПолучателяПисьма;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(СтрокаПараметрыПисьма.ТекстПисьма) Тогда
		СтрокаПараметрыПисьма.ТекстПисьма =
		        СтрокаПараметрыПисьма.ТекстПисьма + Символы.ПС
		        + "------------------------------------"  + Символы.ПС;
	КонецЕсли;
	
	СтрокаПараметрыПисьма.КоличествоЗадач = СтрокаПараметрыПисьма.КоличествоЗадач + 1;
	СтрокаПараметрыПисьма.ТекстПисьма = СтрокаПараметрыПисьма.ТекстПисьма + ТекстПисьма;
	
КонецПроцедуры

Функция ВыбратьПросроченныеЗадачи()
	
	ПросроченныеЗадачи = СписокПросроченныхЗадач();
	
	Индекс = ПросроченныеЗадачи.Количество() - 1;
	Пока Индекс >= 0 Цикл
		ПросроченнаяЗадача = ПросроченныеЗадачи.Получить(Индекс);
		Если НЕ ЗначениеЗаполнено(ПросроченнаяЗадача.Исполнитель) И БизнесПроцессыИЗадачиВызовСервера.ЭтоВедущаяЗадача(ПросроченнаяЗадача.Ссылка) Тогда
			ПросроченныеЗадачи.Удалить(ПросроченнаяЗадача);
		КонецЕсли;
		Индекс = Индекс - 1;
	КонецЦикла;
	
	Возврат ПросроченныеЗадачи;
	
КонецФункции

// Возвращаемое значение:
//  ТаблицаЗначений:
//    * Ссылка - ЗадачаСсылка.ЗадачаИсполнителя
//    * СрокИсполнения - Дата
//    * Исполнитель - СправочникСсылка.ВнешниеПользователи
//                  - СправочникСсылка.Пользователи
//    * РольИсполнителя - СправочникСсылка.РолиИсполнителей
//    * ОсновнойОбъектАдресации - Характеристика.ОбъектыАдресацииЗадач
//    * ДополнительныйОбъектАдресации - Характеристика.ОбъектыАдресацииЗадач
//    * Автор - СправочникСсылка.ВнешниеПользователи
//            - СправочникСсылка.Пользователи
//    * Описание - Строка
// 
Функция СписокПросроченныхЗадач()

	ТекстЗапроса = 
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	ЗадачаИсполнителя.Ссылка КАК Ссылка,
		|	ЗадачаИсполнителя.СрокИсполнения КАК СрокИсполнения,
		|	ЗадачаИсполнителя.Исполнитель КАК Исполнитель,
		|	ЗадачаИсполнителя.РольИсполнителя КАК РольИсполнителя,
		|	ЗадачаИсполнителя.ОсновнойОбъектАдресации КАК ОсновнойОбъектАдресации,
		|	ЗадачаИсполнителя.ДополнительныйОбъектАдресации КАК ДополнительныйОбъектАдресации,
		|	ЗадачаИсполнителя.Автор КАК Автор,
		|	ЗадачаИсполнителя.Описание КАК Описание
		|ИЗ
		|	Задача.ЗадачаИсполнителя КАК ЗадачаИсполнителя
		|ГДЕ
		|	ЗадачаИсполнителя.ПометкаУдаления = ЛОЖЬ
		|	И ЗадачаИсполнителя.Выполнена = ЛОЖЬ
		|	И ЗадачаИсполнителя.СрокИсполнения <= &Дата
		|	И ЗадачаИсполнителя.СостояниеБизнесПроцесса <> ЗНАЧЕНИЕ(Перечисление.СостоянияБизнесПроцессов.Остановлен)";
	
	СрокИсполнения = КонецДня(ТекущаяДатаСеанса());

	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	Запрос.УстановитьПараметр("Дата", СрокИсполнения);
	
	ПросроченныеЗадачи = Запрос.Выполнить().Выгрузить();
	Возврат ПросроченныеЗадачи;
	
КонецФункции

Функция ПисьмаОПросроченныхЗадачах(ПросроченныеЗадачи)
	
	КоординаторыЗадач = Новый Соответствие;
	ПолучателиПисем = Новый Массив;
	ЗадачиСРолевойАдресацией = Новый Массив;
	Для Каждого ПросроченнаяЗадача Из ПросроченныеЗадачи Цикл
		ПросроченнаяЗадачаСсылка = ПросроченнаяЗадача.Ссылка;
		ПолучателиПисем.Добавить(ПросроченнаяЗадача.Автор);
		Если ЗначениеЗаполнено(ПросроченнаяЗадача.Исполнитель) Тогда
			ПолучателиПисем.Добавить(ПросроченнаяЗадача.Исполнитель);
		Иначе
			ЗадачиСРолевойАдресацией.Добавить(ПросроченнаяЗадача);
			Координаторы = НайтиОтветственныхЗаНазначениеРолей(ПросроченнаяЗадача.ОсновнойОбъектАдресации, 
				ПросроченнаяЗадача.ДополнительныйОбъектАдресации);
			КоординаторыЗадач[ПросроченнаяЗадачаСсылка] = Координаторы;
			Для Каждого Координатор Из Координаторы Цикл
				ПолучателиПисем.Добавить(Координатор);
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;

	ИсполнителиЗадач = ИсполнителиЗадач(ЗадачиСРолевойАдресацией);
	ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ПолучателиПисем, ИсполнителиЗадач.Исполнители);
	ПолучателиПисем = ОбщегоНазначенияКлиентСервер.СвернутьМассив(ПолучателиПисем);
	АдресаПолучателей = АдресаЭлектроннойПочты(ПолучателиПисем);

	НаборПисемПоАдресатам = Новый ТаблицаЗначений;
	НаборПисемПоАдресатам.Колонки.Добавить("ПочтовыйАдрес");
	НаборПисемПоАдресатам.Колонки.Добавить("ТекстПисьма");
	НаборПисемПоАдресатам.Колонки.Добавить("КоличествоЗадач");
	НаборПисемПоАдресатам.Колонки.Добавить("ТипПисьма");
	НаборПисемПоАдресатам.Колонки.Добавить("Получатель");
	НаборПисемПоАдресатам.Индексы.Добавить("ТипПисьма, ПочтовыйАдрес");
	
	Для Каждого ПросроченнаяЗадача Из ПросроченныеЗадачи Цикл
		ПросроченнаяЗадачаСсылка = ПросроченнаяЗадача.Ссылка;
		
		ТекстПисьма = СформироватьПредставлениеЗадачи(ПросроченнаяЗадача);
		Если ЗначениеЗаполнено(ПросроченнаяЗадача.Исполнитель) Тогда
			ПолучательПисьма = АдресЭлектроннойПочты(АдресаПолучателей, ПросроченнаяЗадача.Исполнитель);
			НайтиПисьмоИДобавитьТекст(НаборПисемПоАдресатам, ПолучательПисьма, ПросроченнаяЗадача.Исполнитель, ТекстПисьма, "Исполнителю");
		Иначе
			Исполнители = ИсполнителиЗадач.ПоЗадачам[ПросроченнаяЗадачаСсылка];
			Координаторы = КоординаторыЗадач[ПросроченнаяЗадачаСсылка];
			Если Исполнители.Количество() > 0 Тогда
				Для Каждого Исполнитель Из Исполнители Цикл
					ПолучательПисьма = АдресЭлектроннойПочты(АдресаПолучателей, Исполнитель);
					НайтиПисьмоИДобавитьТекст(НаборПисемПоАдресатам, ПолучательПисьма, Исполнитель, ТекстПисьма, "Исполнителю");
				КонецЦикла;
			Иначе	// Задачу исполнять некому.
				СоздатьЗадачуПоНастройкеРолей(ПросроченнаяЗадачаСсылка, Координаторы);
			КонецЕсли;
			
			Для Каждого Координатор Из Координаторы Цикл
				ПолучательПисьма = АдресЭлектроннойПочты(АдресаПолучателей, Координатор);
				НайтиПисьмоИДобавитьТекст(НаборПисемПоАдресатам, ПолучательПисьма, Координатор, ТекстПисьма, "Координатору");
			КонецЦикла;
		КонецЕсли;
		ПолучательПисьма = АдресЭлектроннойПочты(АдресаПолучателей, ПросроченнаяЗадача.Автор);
		НайтиПисьмоИДобавитьТекст(НаборПисемПоАдресатам, ПолучательПисьма, ПросроченнаяЗадача.Автор, ТекстПисьма, "Автору");
	КонецЦикла;
	
	Возврат НаборПисемПоАдресатам;
	
КонецФункции

Процедура ОтправитьУведомлениеОПросроченноеЗадаче(Письмо)
	
	Если ПустаяСтрока(Письмо.ПочтовыйАдрес) Тогда
		ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Уведомление не было отправлено, так как не задан адрес электронной почты у исполнителя задачи %1.'"), 
			ОбщегоНазначения.ПредметСтрокой(Письмо.Получатель));
		ЗаписьЖурналаРегистрации(НСтр("ru = 'Бизнес-процессы и задачи.Уведомление о просроченных задачах'", 
			ОбщегоНазначения.КодОсновногоЯзыка()),
			УровеньЖурналаРегистрации.Информация,,, ТекстСообщения);
		Возврат;
	КонецЕсли;
	
	ПараметрыПисьма = Новый Структура;
	ПараметрыПисьма.Вставить("Кому", Письмо.ПочтовыйАдрес);
	Если Письмо.ТипПисьма = "Исполнителю" Тогда
		ТекстТелаПисьма = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Не выполненные в срок задачи:
			| 
			|%1'"), Письмо.ТекстПисьма);
		ПараметрыПисьма.Вставить("Тело", ТекстТелаПисьма);
		
		ТекстТемыПисьма = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Не выполненные в срок задачи (%1)'"),
			Строка(Письмо.КоличествоЗадач ));
		ПараметрыПисьма.Вставить("Тема", ТекстТемыПисьма);
	ИначеЕсли Письмо.ТипПисьма = "Автору" Тогда
		ТекстТелаПисьма = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'По введенным задачам прошел крайний срок:
			| 
			|%1'"), Письмо.ТекстПисьма);
		ПараметрыПисьма.Вставить("Тело", ТекстТелаПисьма);
		
		ТекстТемыПисьма = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'По задачам истек контрольный срок (%1)'"),
			Строка(Письмо.КоличествоЗадач));
		ПараметрыПисьма.Вставить("Тема", ТекстТемыПисьма);
	ИначеЕсли Письмо.ТипПисьма = "Координатору" Тогда
		ТекстТелаПисьма = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Прошел крайний срок по задачам:
			| 
			|%1'"), Письмо.ТекстПисьма);
		ПараметрыПисьма.Вставить("Тело", ТекстТелаПисьма);
		
		ТекстТемыПисьма = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Истек контрольный срок задач (%1)'"),
			Строка(Письмо.КоличествоЗадач));
		ПараметрыПисьма.Вставить("Тема", ТекстТемыПисьма);
	КонецЕсли;
	
	ТекстСообщения = "";
	
	МодульРаботаСПочтовымиСообщениями = ОбщегоНазначения.ОбщийМодуль("РаботаСПочтовымиСообщениями");
	Попытка
		УчетнаяЗапись = МодульРаботаСПочтовымиСообщениями.СистемнаяУчетнаяЗапись();
		Письмо = МодульРаботаСПочтовымиСообщениями.ПодготовитьПисьмо(УчетнаяЗапись, ПараметрыПисьма);
		МодульРаботаСПочтовымиСообщениями.ОтправитьПисьмо(УчетнаяЗапись, Письмо);
	Исключение
		ОписаниеОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Не отправлены уведомления о просроченных задачах по причине: 
				|%1.'"),
			ОписаниеОшибки);
		УровеньВажностиСобытия = УровеньЖурналаРегистрации.Ошибка;
	КонецПопытки;
	
	Если ПустаяСтрока(ТекстСообщения) Тогда
		Если ПараметрыПисьма.Кому.Количество() > 0 Тогда
			Кому = ? (ПустаяСтрока(ПараметрыПисьма.Кому[0].Представление),
						ПараметрыПисьма.Кому[0].Адрес,
						ПараметрыПисьма.Кому[0].Представление + " <" + ПараметрыПисьма.Кому[0].Адрес + ">");
		КонецЕсли;
		
		ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Уведомление о просроченных задачах успешно отправлено на адрес %1.'"), Кому);
		УровеньВажностиСобытия = УровеньЖурналаРегистрации.Информация;
	КонецЕсли;
	
	ЗаписьЖурналаРегистрации(НСтр("ru = 'Бизнес-процессы и задачи.Уведомление о просроченных задачах'",
		ОбщегоНазначения.КодОсновногоЯзыка()), 
		УровеньВажностиСобытия,,, ТекстСообщения);
		
КонецПроцедуры

Процедура СоздатьЗадачуПоНастройкеРолей(ЗадачаСсылка, Ответственные)
	
	Для Каждого Ответственный Из Ответственные Цикл
		ЗадачаОбъект = Задачи.ЗадачаИсполнителя.СоздатьЗадачу();
		ЗадачаОбъект.Дата = ТекущаяДатаСеанса();
		ЗадачаОбъект.Важность = Перечисления.ВариантыВажностиЗадачи.Высокая;
		ЗадачаОбъект.Исполнитель = Ответственный;
		ЗадачаОбъект.Предмет = ЗадачаСсылка;

		ЗадачаОбъект.Описание = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Задача не может быть исполнена, так как у роли не задано ни одного исполнителя:
		    |%1'"), Строка(ЗадачаСсылка));
		ЗадачаОбъект.Наименование = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Назначить исполнителей: задача не может быть исполнена %1'"), Строка(ЗадачаСсылка));
		ЗадачаОбъект.Записать();
	КонецЦикла;
	
КонецПроцедуры

Функция ВыбратьНовыеЗадачиПоИсполнителям(Знач ДатаВремяОт, Знач ДатаВремяПо)
	
	Запрос = Новый Запрос(
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	ЗадачаИсполнителя.Ссылка КАК Ссылка,
		|	ЗадачаИсполнителя.Номер КАК Номер,
		|	ЗадачаИсполнителя.Дата КАК Дата,
		|	ЗадачаИсполнителя.Наименование КАК Наименование,
		|	ЗадачаИсполнителя.СрокИсполнения КАК СрокИсполнения,
		|	ЗадачаИсполнителя.Автор КАК Автор,
		|	ЗадачаИсполнителя.Описание КАК Описание,
		|	ВЫБОР
		|		КОГДА ЗадачаИсполнителя.Исполнитель <> НЕОПРЕДЕЛЕНО
		|			ТОГДА ЗадачаИсполнителя.Исполнитель
		|		ИНАЧЕ ИсполнителиЗадач.Исполнитель
		|	КОНЕЦ КАК Исполнитель,
		|	ЗадачаИсполнителя.РольИсполнителя КАК РольИсполнителя,
		|	ЗадачаИсполнителя.ОсновнойОбъектАдресации КАК ОсновнойОбъектАдресации,
		|	ЗадачаИсполнителя.ДополнительныйОбъектАдресации КАК ДополнительныйОбъектАдресации
		|ИЗ
		|	Задача.ЗадачаИсполнителя КАК ЗадачаИсполнителя
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИсполнителиЗадач КАК ИсполнителиЗадач
		|		ПО ЗадачаИсполнителя.РольИсполнителя = ИсполнителиЗадач.РольИсполнителя
		|			И ЗадачаИсполнителя.ОсновнойОбъектАдресации = ИсполнителиЗадач.ОсновнойОбъектАдресации
		|			И ЗадачаИсполнителя.ДополнительныйОбъектАдресации = ИсполнителиЗадач.ДополнительныйОбъектАдресации
		|ГДЕ
		|	ЗадачаИсполнителя.Выполнена = ЛОЖЬ
		|	И ЗадачаИсполнителя.Дата МЕЖДУ &ДатаВремяОт И &ДатаВремяПо
		|	И ЗадачаИсполнителя.ПометкаУдаления = ЛОЖЬ
		|	И (ЗадачаИсполнителя.Исполнитель <> ЗНАЧЕНИЕ(Справочник.Пользователи.ПустаяСсылка)
		|			ИЛИ ИсполнителиЗадач.Исполнитель ЕСТЬ НЕ NULL 
		|		И ИсполнителиЗадач.Исполнитель <> ЗНАЧЕНИЕ(Справочник.Пользователи.ПустаяСсылка))
		|
		|УПОРЯДОЧИТЬ ПО
		|	Исполнитель,
		|	СрокИсполнения УБЫВ
		|ИТОГИ ПО
		|	Исполнитель");
	Запрос.Параметры.Вставить("ДатаВремяОт", ДатаВремяОт + 1);
	Запрос.Параметры.Вставить("ДатаВремяПо", ДатаВремяПо);
	Результат = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
	
	Возврат Результат;
	
КонецФункции

Функция ОтправитьУведомлениеОНовыхЗадачах(Исполнитель, ЗадачиПоИсполнителю, АдресаПолучателей)
	
	ПочтовыйАдресПолучателя = АдресЭлектроннойПочты(АдресаПолучателей, Исполнитель);
	Если ПустаяСтрока(ПочтовыйАдресПолучателя) Тогда
		ЗаписьЖурналаРегистрации(НСтр("ru = 'Бизнес-процессы и задачи.Уведомление о новых задачах'", ОбщегоНазначения.КодОсновногоЯзыка()),
			УровеньЖурналаРегистрации.Информация,,,
			СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Уведомление не отправлено, так как не указан почтовый адрес у исполнителя задачи %1.'"), 
				ОбщегоНазначения.ПредметСтрокой(Исполнитель)));
		Возврат Ложь;
	КонецЕсли;
	
	ТекстПисьма = "";
	Для Каждого Задача Из ЗадачиПоИсполнителю.Строки Цикл
		ТекстПисьма = ТекстПисьма + СформироватьПредставлениеЗадачи(Задача);
	КонецЦикла;
	ТемаПисьма = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Направлены задачи - %1'"), Метаданные.КраткаяИнформация);
	
	ПараметрыПисьма = Новый Структура;
	ПараметрыПисьма.Вставить("Тема", ТемаПисьма);
	ПараметрыПисьма.Вставить("Тело", ТекстПисьма);
	ПараметрыПисьма.Вставить("Кому", ПочтовыйАдресПолучателя);
	
	МодульРаботаСПочтовымиСообщениями = ОбщегоНазначения.ОбщийМодуль("РаботаСПочтовымиСообщениями");
	Попытка 
		УчетнаяЗапись = МодульРаботаСПочтовымиСообщениями.СистемнаяУчетнаяЗапись();
		Письмо = МодульРаботаСПочтовымиСообщениями.ПодготовитьПисьмо(УчетнаяЗапись, ПараметрыПисьма);
		МодульРаботаСПочтовымиСообщениями.ОтправитьПисьмо(УчетнаяЗапись, Письмо);
	Исключение
		ЗаписьЖурналаРегистрации(НСтр("ru = 'Бизнес-процессы и задачи.Уведомление о новых задачах'",
			ОбщегоНазначения.КодОсновногоЯзыка()), 
			УровеньЖурналаРегистрации.Ошибка,,,
			СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Уведомления о новых задачах не отправлены по причине:
				|%1'"), 
				ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
		Возврат Ложь;
	КонецПопытки;

	ЗаписьЖурналаРегистрации(НСтр("ru = 'Бизнес-процессы и задачи.Уведомление о новых задачах'",
		ОбщегоНазначения.КодОсновногоЯзыка()),
		УровеньЖурналаРегистрации.Информация,,,
		СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Уведомления успешно отправлены на адрес %1.'"), 
			ПочтовыйАдресПолучателя));
	Возврат Истина;	
		
КонецФункции

Функция СформироватьПредставлениеЗадачи(ЗадачаСтруктура)
	
	Результат = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1
		|
		|Крайний срок: %2'") + Символы.ПС,
		ЗадачаСтруктура.Ссылка, 
		Формат(ЗадачаСтруктура.СрокИсполнения, НСтр("ru = 'ДЛФ=DD; ДП=''не указан'''")));
	Если ЗначениеЗаполнено(ЗадачаСтруктура.Исполнитель) Тогда
		Результат = Результат + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Исполнитель: %1'"), 
			ЗадачаСтруктура.Исполнитель) + Символы.ПС;
	КонецЕсли;
	Если ЗначениеЗаполнено(ЗадачаСтруктура.РольИсполнителя) Тогда
		Результат = Результат + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Роль: %1'"), 
			ЗадачаСтруктура.РольИсполнителя) + Символы.ПС;
	КонецЕсли;
	Если ЗначениеЗаполнено(ЗадачаСтруктура.ОсновнойОбъектАдресации) Тогда
		Результат = Результат + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Основной объект адресации: %1'"), 
			ЗадачаСтруктура.ОсновнойОбъектАдресации) + Символы.ПС;
	КонецЕсли;
	Если ЗначениеЗаполнено(ЗадачаСтруктура.ДополнительныйОбъектАдресации) Тогда
		Результат = Результат + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Доп. объект адресации: %1'"), 
			ЗадачаСтруктура.ДополнительныйОбъектАдресации) + Символы.ПС;
	КонецЕсли;
	Если ЗначениеЗаполнено(ЗадачаСтруктура.Автор) Тогда
		Результат = Результат + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Автор: %1'"), 
			ЗадачаСтруктура.Автор) + Символы.ПС;
	КонецЕсли;
	Если ЗначениеЗаполнено(ЗадачаСтруктура.Описание) Тогда
		Результат = Результат + Символы.ПС + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1'"), 
			ЗадачаСтруктура.Описание) + Символы.ПС;
	КонецЕсли;
	Возврат Результат + Символы.ПС;
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Вспомогательные процедуры и функции.

Функция ВыбратьРолиСКоличествомИсполнителей(ОсновнойОбъектАдресации) Экспорт
	Если ОсновнойОбъектАдресации <> Неопределено Тогда
		ТекстЗапроса = 
			"ВЫБРАТЬ РАЗРЕШЕННЫЕ
			|	РолиИсполнителей.Ссылка КАК РольСсылка,
			|	РолиИсполнителей.Наименование КАК Роль,
			|	РолиИсполнителей.ВнешняяРоль КАК ВнешняяРоль,
			|	РолиИсполнителей.ТипыОсновногоОбъектаАдресации КАК ТипыОсновногоОбъектаАдресации,
			|	СУММА(ВЫБОР
			|			КОГДА ИсполнителиЗадач.РольИсполнителя <> ЗНАЧЕНИЕ(Справочник.РолиИсполнителей.ПустаяСсылка) 
			|				И ИсполнителиЗадач.РольИсполнителя ЕСТЬ НЕ NULL 
			|				И ИсполнителиЗадач.ОсновнойОбъектАдресации = &ОсновнойОбъектАдресации
			|				ТОГДА 1
			|			ИНАЧЕ 0
			|		КОНЕЦ) КАК Исполнители
			|ИЗ
			|	Справочник.РолиИсполнителей КАК РолиИсполнителей
			|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИсполнителиЗадач КАК ИсполнителиЗадач
			|		ПО (ИсполнителиЗадач.РольИсполнителя = РолиИсполнителей.Ссылка)
			|ГДЕ
			|	РолиИсполнителей.ПометкаУдаления = ЛОЖЬ
			|	И РолиИсполнителей.ИспользуетсяСОбъектамиАдресации = ИСТИНА
			| СГРУППИРОВАТЬ ПО
			|	РолиИсполнителей.Ссылка,
			|	ИсполнителиЗадач.РольИсполнителя, 
			|	РолиИсполнителей.ВнешняяРоль,
			|	РолиИсполнителей.Наименование,
			|	РолиИсполнителей.ТипыОсновногоОбъектаАдресации";
	Иначе
		ТекстЗапроса = 
			"ВЫБРАТЬ РАЗРЕШЕННЫЕ
			|	РолиИсполнителей.Ссылка КАК РольСсылка,
			|	РолиИсполнителей.Наименование КАК Роль,
			|	РолиИсполнителей.ВнешняяРоль КАК ВнешняяРоль,
			|	РолиИсполнителей.ТипыОсновногоОбъектаАдресации КАК ТипыОсновногоОбъектаАдресации,
			|	СУММА(ВЫБОР
			|			КОГДА ИсполнителиЗадач.РольИсполнителя <> ЗНАЧЕНИЕ(Справочник.РолиИсполнителей.ПустаяСсылка) 
			|				И ИсполнителиЗадач.РольИсполнителя ЕСТЬ НЕ NULL 
			|				И (ИсполнителиЗадач.ОсновнойОбъектАдресации ЕСТЬ NULL 
			|					ИЛИ ИсполнителиЗадач.ОсновнойОбъектАдресации = Неопределено)
			|				ТОГДА 1
			|			ИНАЧЕ 0
			|		КОНЕЦ) КАК Исполнители
			|ИЗ
			|	Справочник.РолиИсполнителей КАК РолиИсполнителей
			|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИсполнителиЗадач КАК ИсполнителиЗадач
			|		ПО (ИсполнителиЗадач.РольИсполнителя = РолиИсполнителей.Ссылка)
			|ГДЕ
			|	РолиИсполнителей.ПометкаУдаления = ЛОЖЬ
			|	И РолиИсполнителей.ИспользуетсяБезОбъектовАдресации = ИСТИНА
			| СГРУППИРОВАТЬ ПО
			|	РолиИсполнителей.Ссылка,
			|	ИсполнителиЗадач.РольИсполнителя, 
			|	РолиИсполнителей.ВнешняяРоль,
			|	РолиИсполнителей.Наименование, 
			|	РолиИсполнителей.ТипыОсновногоОбъектаАдресации";
	КонецЕсли;
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
		
		МодульМультиязычностьСервер = ОбщегоНазначения.ОбщийМодуль("МультиязычностьСервер");
		СуффиксТекущегоЯзыка = МодульМультиязычностьСервер.СуффиксТекущегоЯзыка();

		Если ЗначениеЗаполнено(СуффиксТекущегоЯзыка) Тогда
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "РолиИсполнителей.Наименование", 
				"РолиИсполнителей.Наименование" + СуффиксТекущегоЯзыка);
		КонецЕсли;
		
	КонецЕсли;
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.Параметры.Вставить("ОсновнойОбъектАдресации", ОсновнойОбъектАдресации);
	ВыборкаЗапроса = Запрос.Выполнить().Выбрать();
	Возврат ВыборкаЗапроса;
	
КонецФункции

// Есть ли хотя бы один исполнитель, назначенный на указанную роль.
//
// Возвращаемое значение:
//   Булево
//
Функция ЕстьИсполнителиРоли(РольСсылка, ОсновнойОбъектАдресации = Неопределено,
	ДополнительныйОбъектАдресации = Неопределено) Экспорт
	
	РезультатЗапроса = ВыбратьИсполнителейРоли(РольСсылка, ОсновнойОбъектАдресации,
		ДополнительныйОбъектАдресации);
	Возврат НЕ РезультатЗапроса.Пустой();	
	
КонецФункции

Функция ВыбратьИсполнителейРоли(РольСсылка, ОсновнойОбъектАдресации = Неопределено,
	ДополнительныйОбъектАдресации = Неопределено)
	
	ТекстЗапроса = 
		"ВЫБРАТЬ
	   |	ИсполнителиЗадач.Исполнитель
	   |ИЗ
	   |	РегистрСведений.ИсполнителиЗадач КАК ИсполнителиЗадач
	   |ГДЕ
	   |	ИсполнителиЗадач.РольИсполнителя = &РольИсполнителя";
	Если ОсновнойОбъектАдресации <> Неопределено Тогда  
		ТекстЗапроса = ТекстЗапроса 
			+ "	И ИсполнителиЗадач.ОсновнойОбъектАдресации = &ОсновнойОбъектАдресации";
	КонецЕсли;		
	Если ДополнительныйОбъектАдресации <> Неопределено Тогда  
		ТекстЗапроса = ТекстЗапроса 
			+ "	И ИсполнителиЗадач.ДополнительныйОбъектАдресации = &ДополнительныйОбъектАдресации";
	КонецЕсли;		
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.Параметры.Вставить("РольИсполнителя", РольСсылка);
	Запрос.Параметры.Вставить("ОсновнойОбъектАдресации", ОсновнойОбъектАдресации);
	Запрос.Параметры.Вставить("ДополнительныйОбъектАдресации", ДополнительныйОбъектАдресации);
	РезультатЗапроса = Запрос.Выполнить();
	Возврат РезультатЗапроса;
	
КонецФункции

Функция ВыбратьИсполнителя(ОсновнойОбъектАдресации, РольИсполнителя) Экспорт
	
	Запрос = Новый Запрос(
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
		|	ИсполнителиЗадач.Исполнитель КАК Исполнитель
		|ИЗ
		|	РегистрСведений.ИсполнителиЗадач КАК ИсполнителиЗадач
		|ГДЕ
		|	ИсполнителиЗадач.РольИсполнителя = &РольИсполнителя
		|	И ИсполнителиЗадач.ОсновнойОбъектАдресации = &ОсновнойОбъектАдресации");
	Запрос.Параметры.Вставить("ОсновнойОбъектАдресации", ОсновнойОбъектАдресации);
	Запрос.Параметры.Вставить("РольИсполнителя", РольИсполнителя);
	ВыборкаЗапроса = Запрос.Выполнить().Выгрузить();
	Возврат ?(ВыборкаЗапроса.Количество() > 0, ВыборкаЗапроса[0].Исполнитель, Справочники.Пользователи.ПустаяСсылка());
	
КонецФункции	

Функция ВыбратьБизнесПроцессыВедущейЗадачи(ЗадачаСсылка, ДляИзменения = Ложь) Экспорт
	
	ШаблонЗапроса = "ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	Таблица.Ссылка КАК Ссылка
		|ИЗ
		|	&ИмяТаблицы КАК Таблица
		|ГДЕ
		|	Таблица.ВедущаяЗадача = &ВедущаяЗадача";
	ТекстыЗапросов = Новый Массив;
	Для Каждого ТипБизнесПроцесса Из Метаданные.ОпределяемыеТипы.БизнесПроцесс.Тип.Типы() Цикл
		
		МетаданныеБизнесПроцесса = Метаданные.НайтиПоТипу(ТипБизнесПроцесса);
		
		Если ДляИзменения Тогда
			Блокировка = Новый БлокировкаДанных;
			ЭлементБлокировки = Блокировка.Добавить(МетаданныеБизнесПроцесса.ПолноеИмя());
			ЭлементБлокировки.УстановитьЗначение("ВедущаяЗадача", ЗадачаСсылка);
			Блокировка.Заблокировать();
		КонецЕсли;
		
		ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&ИмяТаблицы", МетаданныеБизнесПроцесса.ПолноеИмя());
		Если ТекстыЗапросов.Количество() > 0 Тогда
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ РАЗРЕШЕННЫЕ", "ВЫБРАТЬ"); // @Query-part-1, @Query-part-2
		КонецЕсли;
		ТекстыЗапросов.Добавить(ТекстЗапроса);

	КонецЦикла;
	
	Запрос = Новый Запрос(СтрСоединить(ТекстыЗапросов, Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС));
	Запрос.УстановитьПараметр("ВедущаяЗадача", ЗадачаСсылка);
	Возврат Запрос.Выполнить();
	
КонецФункции

Функция СобытиеЖурналаРегистрации() Экспорт
	Возврат НСтр("ru = 'Бизнес-процессы и задачи'", ОбщегоНазначения.КодОсновногоЯзыка());
КонецФункции

// Вызывается при изменении состояния бизнес-процесса для того, чтобы 
// распространить это изменение состояния на невыполненные задачи этого 
// бизнес-процесса.
//
// Параметры:
//   БизнесПроцессОбъект - ОпределяемыйТип.БизнесПроцессОбъект
//   СтароеСостояние - ПеречислениеСсылка.СостоянияБизнесПроцессов
// 
Процедура ПриИзмененииСостоянияБизнесПроцесса(БизнесПроцессОбъект, СтароеСостояние) Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	ЗадачаИсполнителя.Ссылка КАК Ссылка
		|ИЗ
		|	Задача.ЗадачаИсполнителя КАК ЗадачаИсполнителя
		|ГДЕ
		|	ЗадачаИсполнителя.БизнесПроцесс = &БизнесПроцесс
		|	И ЗадачаИсполнителя.Выполнена = ЛОЖЬ";

	Запрос.УстановитьПараметр("БизнесПроцесс", БизнесПроцессОбъект.Ссылка);

	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("Задача.ЗадачаИсполнителя");
	ЭлементБлокировки.УстановитьЗначение("БизнесПроцесс", БизнесПроцессОбъект.Ссылка);
	Блокировка.Заблокировать();
	
	НевыполненныеЗадачи = Запрос.Выполнить().Выгрузить();
	Для каждого ЗадачаСсылка Из НевыполненныеЗадачи Цикл
		Задача = ЗадачаСсылка.Ссылка.ПолучитьОбъект();
		Задача.Заблокировать();
		Задача.СостояниеБизнесПроцесса = БизнесПроцессОбъект.Состояние;
		Задача.Записать();
	КонецЦикла;
	ПриИзмененииСостоянияЗадач(НевыполненныеЗадачи, СтароеСостояние, БизнесПроцессОбъект.Состояние);

КонецПроцедуры

// Параметры:
//  Задачи - ТаблицаЗначений:
//    * Ссылка - ЗадачаСсылка.ЗадачаИсполнителя
//  СтароеСостояние - ПеречислениеСсылка.СостоянияБизнесПроцессов 
//  НовоеСостояние - ПеречислениеСсылка.СостоянияБизнесПроцессов
//
Процедура ПриИзмененииСостоянияЗадач(Задачи, СтароеСостояние, НовоеСостояние)
	
	// Блокируем вложенные и подчиненные бизнес-процессы.
	Блокировка = Новый БлокировкаДанных;
	Для каждого МетаданныеБизнесПроцесса Из Метаданные.БизнесПроцессы Цикл
		
		Если Не ПравоДоступа("Изменение", МетаданныеБизнесПроцесса) Тогда
			Продолжить;
		КонецЕсли;
		
		ЭлементБлокировки = Блокировка.Добавить(МетаданныеБизнесПроцесса.ПолноеИмя());
		ЭлементБлокировки.ИсточникДанных = Задачи;
		ЭлементБлокировки.ИспользоватьИзИсточникаДанных("ВедущаяЗадача", "Ссылка");
		
		РеквизитГлавнаяЗадача = МетаданныеБизнесПроцесса.Реквизиты.Найти("ГлавнаяЗадача");
		Если РеквизитГлавнаяЗадача <> Неопределено Тогда
			ЭлементБлокировки = Блокировка.Добавить(МетаданныеБизнесПроцесса.ПолноеИмя());
			ЭлементБлокировки.ИсточникДанных = Задачи;
			ЭлементБлокировки.ИспользоватьИзИсточникаДанных("ГлавнаяЗадача", "Ссылка");
		КонецЕсли;
		
	КонецЦикла;
	Блокировка.Заблокировать();
	
	ЗадачиСсылки = Задачи.ВыгрузитьКолонку("Ссылка");
	ШаблонЗапроса = 
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	БизнесПроцессы.Ссылка КАК Ссылка
		|ИЗ
		|	#БизнесПроцессы КАК БизнесПроцессы
		|ГДЕ
		|  БизнесПроцессы.ВедущаяЗадача В (&Задачи)
		|  И БизнесПроцессы.ПометкаУдаления = ЛОЖЬ
		|	И БизнесПроцессы.Завершен = ЛОЖЬ";
	ТекстыЗапроса = Новый Массив;
	
	// Меняем состояние вложенных и подчиненных бизнес-процессов.
	Для каждого МетаданныеБизнесПроцесса Из Метаданные.БизнесПроцессы Цикл
		
		Если НЕ ПравоДоступа("Изменение", МетаданныеБизнесПроцесса) Тогда
			Продолжить;
		КонецЕсли;
		
		ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "#БизнесПроцессы", МетаданныеБизнесПроцесса.ПолноеИмя());
		Если ТекстыЗапроса.Количество() > 0 Тогда
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ РАЗРЕШЕННЫЕ", "ВЫБРАТЬ"); // @query-part-1, @query-part-2
		КонецЕсли;
		ТекстыЗапроса.Добавить(ТекстЗапроса);
		
	КонецЦикла;
	
	Если ТекстыЗапроса.Количество() > 0 Тогда
		Запрос = Новый Запрос(СтрСоединить(ТекстыЗапроса, Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС)); // @query-part
		Запрос.УстановитьПараметр("Задачи", ЗадачиСсылки);
		
		ВыборкаДетальныеЗаписи = Запрос.Выполнить().Выбрать();
		Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
			БизнесПроцесс = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект(); // БизнесПроцессОбъект
			БизнесПроцесс.Состояние = НовоеСостояние;
			БизнесПроцесс.Записать();
		КонецЦикла;
	КонецЕсли;
	
	ШаблонЗапроса = 
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	БизнесПроцессы.Ссылка КАК Ссылка
		|ИЗ
		|	#БизнесПроцессы КАК БизнесПроцессы
		|ГДЕ
		|   БизнесПроцессы.ГлавнаяЗадача В (&Задачи)
		|   И БизнесПроцессы.ПометкаУдаления = ЛОЖЬ
		| 	И БизнесПроцессы.Завершен = ЛОЖЬ";
	ТекстыЗапроса = Новый Массив;
	
	// Меняем состояние подчиненных бизнес-процессов.
	Для каждого МетаданныеБизнесПроцесса Из Метаданные.БизнесПроцессы Цикл
		
		// У бизнес-процесса может не быть главной задачи.
		РеквизитГлавнаяЗадача = МетаданныеБизнесПроцесса.Реквизиты.Найти("ГлавнаяЗадача");
		Если РеквизитГлавнаяЗадача = Неопределено Тогда
			Продолжить;
		КонецЕсли;	
			
		ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "#БизнесПроцессы", МетаданныеБизнесПроцесса.ПолноеИмя());
		Если ТекстыЗапроса.Количество() > 0 Тогда
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ РАЗРЕШЕННЫЕ", "ВЫБРАТЬ"); // @query-part-1, @query-part-2
		КонецЕсли;
		ТекстыЗапроса.Добавить(ТекстЗапроса);

	КонецЦикла;
	
	Если ТекстыЗапроса.Количество() > 0 Тогда
		Запрос = Новый Запрос(СтрСоединить(ТекстыЗапроса, Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС)); // @query-part
		Запрос.УстановитьПараметр("Задачи", ЗадачиСсылки);
	
		ВыборкаДетальныеЗаписи = Запрос.Выполнить().Выбрать();
		Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
			БизнесПроцесс = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект(); // БизнесПроцессОбъект
			БизнесПроцесс.Состояние = НовоеСостояние;
			БизнесПроцесс.Записать();
		КонецЦикла;
	КонецЕсли;
	
КонецПроцедуры

// Получает группы исполнителей задач согласно новым записям исполнителей задач.
//
// Параметры:
//  НовыеИсполнителиЗадач  - ТаблицаЗначений - выгрузка из набора записей
//                           регистра сведений ИсполнителиЗадач.
//
// Возвращаемое значение:
//   Массив из СправочникСсылка.ГруппыИсполнителейЗадач.
//
Функция ГруппыИсполнителейЗадач(НовыеИсполнителиЗадач) Экспорт
	
	НазванияПолей = "РольИсполнителя, ОсновнойОбъектАдресации, ДополнительныйОбъектАдресации";
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("НовыеЗаписи", НовыеИсполнителиЗадач.Скопировать( , НазванияПолей));
	Запрос.Текст =
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	НовыеЗаписи.РольИсполнителя КАК РольИсполнителя,
	|	НовыеЗаписи.ОсновнойОбъектАдресации КАК ОсновнойОбъектАдресации,
	|	НовыеЗаписи.ДополнительныйОбъектАдресации КАК ДополнительныйОбъектАдресации
	|ПОМЕСТИТЬ НовыеЗаписи
	|ИЗ
	|	&НовыеЗаписи КАК НовыеЗаписи
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ЕСТЬNULL(ГруппыИсполнителейЗадач.Ссылка, ЗНАЧЕНИЕ(Справочник.ГруппыИсполнителейЗадач.ПустаяСсылка)) КАК Ссылка,
	|	НовыеЗаписи.РольИсполнителя КАК РольИсполнителя,
	|	НовыеЗаписи.ОсновнойОбъектАдресации КАК ОсновнойОбъектАдресации,
	|	НовыеЗаписи.ДополнительныйОбъектАдресации КАК ДополнительныйОбъектАдресации
	|ИЗ
	|	НовыеЗаписи КАК НовыеЗаписи
	|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ГруппыИсполнителейЗадач КАК ГруппыИсполнителейЗадач
	|		ПО НовыеЗаписи.РольИсполнителя = ГруппыИсполнителейЗадач.РольИсполнителя
	|			И НовыеЗаписи.ОсновнойОбъектАдресации = ГруппыИсполнителейЗадач.ОсновнойОбъектАдресации
	|			И НовыеЗаписи.ДополнительныйОбъектАдресации = ГруппыИсполнителейЗадач.ДополнительныйОбъектАдресации";
	
	ГруппыИсполнителей = Запрос.Выполнить().Выгрузить();
	
	ОтборГруппыИсполнителей = Новый Структура(НазванияПолей);
	ГруппыИсполнителейЗадач = Новый Массив;
	
	Для каждого Запись Из НовыеИсполнителиЗадач Цикл
		ЗаполнитьЗначенияСвойств(ОтборГруппыИсполнителей, Запись);
		ГруппаИсполнителей = ГруппыИсполнителей.НайтиСтроки(ОтборГруппыИсполнителей)[0];
		// Требуется обновить ссылку в найденной строке.
		Если НЕ ЗначениеЗаполнено(ГруппаИсполнителей.Ссылка) Тогда
			// Требуется добавить новую группу исполнителей.
			ГруппаИсполнителейОбъект = Справочники.ГруппыИсполнителейЗадач.СоздатьЭлемент();
			ЗаполнитьЗначенияСвойств(ГруппаИсполнителейОбъект, ОтборГруппыИсполнителей);
			ГруппаИсполнителейОбъект.Записать();
			ГруппаИсполнителей.Ссылка = ГруппаИсполнителейОбъект.Ссылка;
		КонецЕсли;
		ГруппыИсполнителейЗадач.Добавить(ГруппаИсполнителей.Ссылка);
	КонецЦикла;
	
	Возврат ГруппыИсполнителейЗадач;
	
КонецФункции

// Пометить на удаление вложенные и подчиненные бизнес-процессы задачи ЗадачаСсылка.
//
// Параметры:
//  ЗадачаСсылка                 - ЗадачаСсылка.ЗадачаИсполнителя
//  НовоеЗначениеПометкиУдаления - Булево
//
Процедура ПриПометкеУдаленияЗадачи(ЗадачаСсылка, НовоеЗначениеПометкиУдаления) Экспорт
	
	ОбъектЗадачи = ЗадачаСсылка.Метаданные();
	Если НовоеЗначениеПометкиУдаления Тогда
		ВыполнитьПроверкуПравДоступа("ИнтерактивнаяПометкаУдаления", ОбъектЗадачи);
	КонецЕсли;
	Если Не НовоеЗначениеПометкиУдаления Тогда
		ВыполнитьПроверкуПравДоступа("ИнтерактивноеСнятиеПометкиУдаления", ОбъектЗадачи);
	КонецЕсли;
	Если ЗадачаСсылка.Пустая() Тогда
		Возврат;
	КонецЕсли;
	
	НачатьТранзакцию();
	Попытка
		// Помечаем вложенные бизнес-процессы.
		УстановитьПривилегированныйРежим(Истина);
		ВложенныеБизнесПроцессы = БизнесПроцессыВедущейЗадачи(ЗадачаСсылка, Истина);
		УстановитьПривилегированныйРежим(Ложь);
		// Без привилегированного режима, с проверкой прав.
		Для Каждого ВложенныйБизнесПроцесс Из ВложенныеБизнесПроцессы Цикл
			БизнесПроцессОбъект = ВложенныйБизнесПроцесс.ПолучитьОбъект();
			БизнесПроцессОбъект.УстановитьПометкуУдаления(НовоеЗначениеПометкиУдаления);
		КонецЦикла;
		
		// Помечаем подчиненные бизнес-процессы.
		ПодчиненныеБизнесПроцессы = БизнесПроцессыГлавнойЗадачи(ЗадачаСсылка, Истина);
		Для Каждого ПодчиненныйБизнесПроцесс Из ПодчиненныеБизнесПроцессы Цикл
			БизнесПроцессОбъект = ПодчиненныйБизнесПроцесс.ПолучитьОбъект();
			БизнесПроцессОбъект.Заблокировать();
			БизнесПроцессОбъект.УстановитьПометкуУдаления(НовоеЗначениеПометкиУдаления);
		КонецЦикла;
		
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры

// Проверяет наличие прав для того, чтобы отметить бизнес-процесс
// как остановленный или активный.
// 
// Параметры:
//  БизнесПроцесс - ОпределяемыйТип.БизнесПроцессОбъект
//
// Возвращаемое значение:
//  Булево - Истина, если права есть.
//
Функция ЕстьПраваНаОстановкуБизнесПроцесса(БизнесПроцесс)
	
	ЕстьПрава = Ложь;
	СтандартнаяОбработка = Истина;
	БизнесПроцессыИЗадачиПереопределяемый.ПриПроверкеПравНаОстановкуБизнесПроцесса(БизнесПроцесс, ЕстьПрава, СтандартнаяОбработка);
	Если Не СтандартнаяОбработка Тогда
		Возврат ЕстьПрава;
	КонецЕсли;
	
	Если Пользователи.ЭтоПолноправныйПользователь() Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если БизнесПроцесс.Автор = Пользователи.ТекущийПользователь() Тогда
		Возврат Истина;
	КонецЕсли;
	
	Возврат ЕстьПрава;
	
КонецФункции

// Параметры:
//   Список - ДинамическийСписок
//
Процедура УстановитьПараметрыСпискаМоихЗадач(Список) Экспорт
	
	ТекущаяДатаСеанса = ТекущаяДатаСеанса();
	Сегодня = Новый СтандартныйПериод(ВариантСтандартногоПериода.Сегодня);
	ЭтаНеделя = Новый СтандартныйПериод(ВариантСтандартногоПериода.ЭтаНеделя);
	СледующаяНеделя = Новый СтандартныйПериод(ВариантСтандартногоПериода.СледующаяНеделя);
	
	Список.Параметры.УстановитьЗначениеПараметра("ТекущаяДата", ТекущаяДатаСеанса);
	Список.Параметры.УстановитьЗначениеПараметра("КонецДня", Сегодня.ДатаОкончания);
	Список.Параметры.УстановитьЗначениеПараметра("КонецНедели", ЭтаНеделя.ДатаОкончания);
	Список.Параметры.УстановитьЗначениеПараметра("КонецСледующейНедели", СледующаяНеделя.ДатаОкончания);
	Список.Параметры.УстановитьЗначениеПараметра("Просрочено", " " + НСтр("ru = 'Просрочено'")); // пробел для сортировки
	Список.Параметры.УстановитьЗначениеПараметра("Сегодня", НСтр("ru = 'В течение сегодня'"));
	Список.Параметры.УстановитьЗначениеПараметра("ЭтаНеделя", НСтр("ru = 'До конца недели'"));
	Список.Параметры.УстановитьЗначениеПараметра("СледующаяНеделя", НСтр("ru = 'На следующей неделе'"));
	Список.Параметры.УстановитьЗначениеПараметра("Позднее", НСтр("ru = 'Позднее'"));
	Список.Параметры.УстановитьЗначениеПараметра("НачалоДня", НачалоДня(ТекущаяДатаСеанса));
	Список.Параметры.УстановитьЗначениеПараметра("НезаполненнаяДата", Дата(1,1,1));
	
КонецПроцедуры

Функция КоличествоЗадачИсполнителя()
	
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	ЗадачиПоИсполнителю.Ссылка КАК Ссылка,
	|	ЗадачиПоИсполнителю.СрокИсполнения КАК СрокИсполнения
	|ПОМЕСТИТЬ БизнесПроцессыПользователя
	|ИЗ
	|	Задача.ЗадачаИсполнителя.ЗадачиПоИсполнителю КАК ЗадачиПоИсполнителю
	|ГДЕ
	|	НЕ ЗадачиПоИсполнителю.ПометкаУдаления
	|	И НЕ ЗадачиПоИсполнителю.Выполнена
	|	И ЗадачиПоИсполнителю.СостояниеБизнесПроцесса = ЗНАЧЕНИЕ(Перечисление.СостоянияБизнесПроцессов.Активен)
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	КОЛИЧЕСТВО(БизнесПроцессыПользователя.Ссылка) КАК Количество
	|ИЗ
	|	БизнесПроцессыПользователя КАК БизнесПроцессыПользователя
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	КОЛИЧЕСТВО(БизнесПроцессыПользователя.Ссылка)
	|ИЗ
	|	БизнесПроцессыПользователя КАК БизнесПроцессыПользователя
	|ГДЕ
	|	БизнесПроцессыПользователя.СрокИсполнения <> ДАТАВРЕМЯ(1, 1, 1)
	|	И БизнесПроцессыПользователя.СрокИсполнения <= &ТекущаяДата
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	КОЛИЧЕСТВО(БизнесПроцессыПользователя.Ссылка)
	|ИЗ
	|	БизнесПроцессыПользователя КАК БизнесПроцессыПользователя
	|ГДЕ
	|	БизнесПроцессыПользователя.СрокИсполнения > &ТекущаяДата
	|	И БизнесПроцессыПользователя.СрокИсполнения <= &Сегодня
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	КОЛИЧЕСТВО(БизнесПроцессыПользователя.Ссылка)
	|ИЗ
	|	БизнесПроцессыПользователя КАК БизнесПроцессыПользователя
	|ГДЕ
	|	БизнесПроцессыПользователя.СрокИсполнения > &Сегодня
	|	И БизнесПроцессыПользователя.СрокИсполнения <= &КонецНедели
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	КОЛИЧЕСТВО(БизнесПроцессыПользователя.Ссылка)
	|ИЗ
	|	БизнесПроцессыПользователя КАК БизнесПроцессыПользователя
	|ГДЕ
	|	БизнесПроцессыПользователя.СрокИсполнения > &КонецНедели
	|	И БизнесПроцессыПользователя.СрокИсполнения <= &КонецСледующейНедели";
	
	Сегодня = Новый СтандартныйПериод(ВариантСтандартногоПериода.Сегодня);
	ЭтаНеделя = Новый СтандартныйПериод(ВариантСтандартногоПериода.ЭтаНеделя);
	СледующаяНеделя = Новый СтандартныйПериод(ВариантСтандартногоПериода.СледующаяНеделя);
	
	Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса());
	Запрос.УстановитьПараметр("Сегодня", Сегодня.ДатаОкончания);
	Запрос.УстановитьПараметр("КонецНедели", ЭтаНеделя.ДатаОкончания);
	Запрос.УстановитьПараметр("КонецСледующейНедели", СледующаяНеделя.ДатаОкончания);
	РезультатЗапроса = Запрос.Выполнить().Выгрузить();
	
	Результат = Новый Структура("Всего,Просроченные,НаСегодня,НаНеделю,НаСледующуюНеделю");
	Результат.Всего = РезультатЗапроса[0].Количество;
	Результат.Просроченные = РезультатЗапроса[1].Количество;
	Результат.НаСегодня = РезультатЗапроса[2].Количество;
	Результат.НаНеделю = РезультатЗапроса[3].Количество;
	Результат.НаСледующуюНеделю = РезультатЗапроса[4].Количество;
	
	Возврат Результат;
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Обновление информационной базы.

// Инициализировать предопределенную роль исполнителей ОтветственныйЗаКонтрольИсполнения.
// 
Процедура ЗаполнитьОтветственногоЗаКонтрольИсполнения() Экспорт
	
	ВсеОбъектыАдресации = ПланыВидовХарактеристик.ОбъектыАдресацииЗадач.ВсеОбъектыАдресации;
	
	РольОбъект = Справочники.РолиИсполнителей.ОтветственныйЗаКонтрольИсполнения.ПолучитьОбъект();
	ЗаблокироватьДанныеДляРедактирования(РольОбъект.Ссылка);
	РольОбъект.Наименование = НСтр("ru = 'Координатор выполнения задач'");
	РольОбъект.ИспользуетсяБезОбъектовАдресации = Истина;
	РольОбъект.ИспользуетсяСОбъектамиАдресации = Истина;
	РольОбъект.ТипыОсновногоОбъектаАдресации = ВсеОбъектыАдресации;
	ОбновлениеИнформационнойБазы.ЗаписатьОбъект(РольОбъект);
	
КонецПроцедуры

// Параметры:
//  Получатели - см. УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъектов
//  Получатель - СправочникСсылка.Пользователи, СправочникСсылка.внешниеПользователи 
// 
// Возвращаемое значение:
//  Строка
//
Функция АдресЭлектроннойПочты(Получатели, Получатель)
	
	Если Получатели = Неопределено Тогда
		Возврат "";
	КонецЕсли;

	СтрокиТаблицы = Получатели.НайтиСтроки(Новый Структура("Объект", Получатель));
	Если СтрокиТаблицы.Количество() > 0 Тогда
		Возврат СтрокиТаблицы[0].Представление;
	КонецЕсли;
	
	Возврат "";
	 
КонецФункции

// Параметры:
//   Получатели - Массив из СправочникСсылка.Пользователи
//              - Массив из СправочникСсылка.внешниеПользователи
//   
// Возвращаемое значение:
//   см. УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъектов
//
Функция АдресаЭлектроннойПочты(Получатели)
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.КонтактнаяИнформация") Тогда
		
		МодульУправлениеКонтактнойИнформацией = ОбщегоНазначения.ОбщийМодуль("УправлениеКонтактнойИнформацией");

		ПользователиСсылки = Новый Массив;
		ВнешниеПользователиСсылки = Новый Массив;
		ЕстьАдресаВнешнихПользователей = МодульУправлениеКонтактнойИнформацией.СодержитКонтактнуюИнформацию(Тип("СправочникСсылка.ВнешниеПользователи"));
		Для каждого Получатель Из Получатели Цикл
			Если ТипЗнч(Получатель) = Тип("СправочникСсылка.Пользователи") Тогда
				ПользователиСсылки.Добавить(Получатель);
			ИначеЕсли ЕстьАдресаВнешнихПользователей И ТипЗнч(Получатель) = Тип("СправочникСсылка.ВнешниеПользователи") Тогда
				ВнешниеПользователиСсылки.Добавить(Получатель);
			КонецЕсли;
		КонецЦикла;
	
		ВидКонтактнойИнформации = МодульУправлениеКонтактнойИнформацией.ВидКонтактнойИнформацииПоИмени("EmailПользователя");
		ТипКонтактнойИнформации = МодульУправлениеКонтактнойИнформацией.ТипКонтактнойИнформацииПоНаименованию("АдресЭлектроннойПочты");
		
		Результат = Неопределено;
		Если ПользователиСсылки.Количество() > 0 Тогда
			Результат = МодульУправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъектов(ПользователиСсылки,,
				ВидКонтактнойИнформации, ТекущаяДатаСеанса());
		КонецЕсли;
		
		Если ВнешниеПользователиСсылки.Количество() > 0 Тогда
			РезультатВнешниеПользователи = МодульУправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъектов(
				ВнешниеПользователиСсылки, ТипКонтактнойИнформации,, ТекущаяДатаСеанса());
			Если Результат <> Неопределено Тогда
				ОбщегоНазначенияКлиентСервер.ДополнитьТаблицу(РезультатВнешниеПользователи, Результат);
			КонецЕсли;
		КонецЕсли;
		
		Если Результат <> Неопределено Тогда
			Результат.Индексы.Добавить("Объект");
		КонецЕсли;
		Возврат Результат;
		
	КонецЕсли;
	
	Возврат Новый Массив;
	
КонецФункции

Функция СистемнаяУчетнаяЗаписьНастроена(ОписаниеОшибки)
	
	Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаСПочтовымиСообщениями") Тогда
		ОписаниеОшибки = НСтр("ru = 'Отправка почты не предусмотрена в программе.'");
	Иначе
		МодульРаботаСПочтовымиСообщениями = ОбщегоНазначения.ОбщийМодуль("РаботаСПочтовымиСообщениями");
		Если МодульРаботаСПочтовымиСообщениями.УчетнаяЗаписьНастроена(МодульРаботаСПочтовымиСообщениями.СистемнаяУчетнаяЗапись(), Истина, Ложь) Тогда
			Возврат Истина;
		КонецЕсли;
		ОписаниеОшибки = НСтр("ru = 'Не настроена электронная почта для рассылки уведомлений.'");
	КонецЕсли;
	
	Возврат Ложь;
КонецФункции

// [2.3.3.70] Актуализирует использование регламентного задания СтартОтложенныхПроцессов.
Процедура ОбновитьИспользованиеРегламентныхЗаданий() Экспорт
	
	ПараметрыПоиска = Новый Структура;
	ПараметрыПоиска.Вставить("Метаданные", Метаданные.РегламентныеЗадания.СтартОтложенныхПроцессов);
	СписокЗаданий = РегламентныеЗаданияСервер.НайтиЗадания(ПараметрыПоиска);
	
	ПараметрыЗадания = Новый Структура("Использование", ПолучитьФункциональнуюОпцию("ИспользоватьБизнесПроцессыИЗадачи"));
	Для Каждого Задание Из СписокЗаданий Цикл
		РегламентныеЗаданияСервер.ИзменитьЗадание(Задание, ПараметрыЗадания);
	КонецЦикла;
	
КонецПроцедуры

// Вызывается при переходе на версию конфигурации 3.0.2.131 и при начальном заполнении.
// 
Процедура ЗаполнитьНаименованиеПредопределенногоЭлементаВсеОбъектыАдресации() Экспорт
	
	Ссылка = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ПланыВидовХарактеристик.ОбъектыАдресацииЗадач.ВсеОбъектыАдресации, "Ссылка");
	
	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("ПланВидовХарактеристик.ОбъектыАдресацииЗадач");
	ЭлементБлокировки.УстановитьЗначение("Ссылка", Ссылка);

	НачатьТранзакцию();
	Попытка
		
		Блокировка.Заблокировать();
		
		ВсеОбъектыАдресации = ПланыВидовХарактеристик.ОбъектыАдресацииЗадач.ВсеОбъектыАдресации.ПолучитьОбъект();
		ВсеОбъектыАдресации.Наименование = НСтр("ru = 'Все объекты адресации'");
		ОбновлениеИнформационнойБазы.ЗаписатьОбъект(ВсеОбъектыАдресации);

		ЗафиксироватьТранзакцию();

	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

КонецПроцедуры

// Возвращаемое значение:
//  ТаблицаЗначений:
//   * ЗадачаСсылка - ЗадачаСсылка
//
Функция НовыеЗадачиПоПредмету() Экспорт
	
	СписокТипов = Новый Массив;
	Для каждого МетаданныеЗадачи Из Метаданные.Задачи Цикл
		СписокТипов.Добавить(Тип(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			"%1.%2", "ЗадачаСсылка", МетаданныеЗадачи.Имя)));
	КонецЦикла;
	
	ОписаниеСоставногоТипа = Новый ОписаниеТипов(СписокТипов);
	
	ЗадачиПоПредмету = Новый ТаблицаЗначений;
	ЗадачиПоПредмету.Колонки.Добавить("ЗадачаСсылка", ОписаниеСоставногоТипа);
	Возврат ЗадачиПоПредмету;

КонецФункции

#КонецОбласти